波浪线“〜”是什么意思是什么意思在C ++? [英] What does the tilde "~" mean in C++?

查看:1924
本文介绍了波浪线“〜”是什么意思是什么意思在C ++?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在QT 5.4中开始一个新类,我注意到第二行代码有一个tilda作为其名称的一部分。这是与QT还是C ++相关?这个tilda是什么意思,这里想说什么?

  #includefindapplications.h

FindApplications :: FindApplications()
{

}

FindApplications ::〜FindApplications()
{

}

编辑:我想我知道为什么我没有得到任何搜索结果。

解决方案

析构函数是一个类的特殊成员函数,当它的类的对象超出范围或每当将删除表达式应用于指向该类的对象的指针时。



析构函数将具有与带有波浪符号的类完全相同的名称,它既不能返回值也不能采取任何参数。



当对象的生命周期结束时,析构函数被调用,包括




  • 程序终止,对于具有静态存储持续时间的对象

  • 存储持续时间(自
    C ++ 11起)

  • 结束范围,对于具有自动存储持续时间的对象和
    临时值,其生命通过绑定到引用,

  • delete-expression,用于具有动态存储持续时间的对象,结束
    完整表达式,用于无名临时数;




析构函数也可以直接调用,例如以销毁使用placement-new或通过诸如 std :: allocator :: destroy()的分配器成员函数构造的对象,以销毁通过分配器。
请注意,直接为一个普通对象(如局部变量)调用析构函数会在再次调用析构函数时调用未定义的行为。



在通用上下文中,析构函数调用语法可以与非类类型的对象一起使用;



隐式声明的析构函数



如果没有为类类型提供用户定义的析构函数( struct class union ),编译器将总是声明一个析构函数为 inline public 其类的成员。



已删除隐式声明的析构函数



class T 的隐式声明或默认析构函数未定义(直到C ++ 11)定义为删除(因为C ++ 11),如果下列任何一个为真:




  • T有一个不能被破坏的非静态数据成员(删除了
    或不可访问的析构函数)
  • T具有不能被销毁的直接或虚拟基类(具有
    被删除或不可访问的析构函数)

  • T是一个联合,非平凡析构函数。
    (自C ++ 11起)



隐式声明的析构函数为 virtual (因为基类有一个虚拟析构函数),并且对释放函数(操作符delete())的查找导致对模糊,删除或不可访问函数的调用
简单析构函数



class T 的析构函数在以下所有条件都成立时是微不足道的:




  • 析构函数不是用户提供的(意味着它是
    隐式定义或默认)

  • 析构函数不是虚函数

  • 所有非静态数据成员(非基类类析构函数是
    不是虚拟的)
  • 类型类型(或类型类型的数组)
    有小的析构函数


一个简单的析构函数是一个析构函数, 。具有简单析构函数的对象不需要delete-expression,并且可以通过简单地释放它们的存储器来处理。所有与C语言兼容的数据类型(POD类型)都是可破坏的。



隐式定义析构函数



如果隐式声明的析构函数没有被删除或微不足道,它由编译器定义(即函数体被生成和编译)。这个隐式定义的析构函数有一个空体。



与任何隐式定义的特殊成员函数一样,隐式定义的析构函数的异常规范是非抛出的,除非它直接调用具有不同异常规范的函数(例如,当它必须为成员或具有不同异常规范的基本子对象调用用户定义的析构函数时)。



strong>销毁序列:



对于用户定义或隐式定义的析构函数,在析构函数的主体执行后,编译器调用析构函数类的所有非静态非变体成员,以相反的声明顺序,然后它以相反的结构顺序调用所有直接基类的析构函数(反过来又调用其成员及其基类的析构函数等) ,然后,如果这个对象是大多数派生类,它调用所有虚拟基础的析构函数。



即使直接调用析构函数 obj。〜Foo(); ),〜Foo()中的return语句不会将控制权返回给调用者

p>通过指向base的指针删除对象会调用未定义的行为,除非基类中的析构函数是virtual:

  class Base {
public:
virtual〜Base(){}
};
class Derived:public Base {};
Base * b = new Derived;
delete b; // safe

一个常见的准则是,基类的析构函数必须是public和virtual受保护和非虚拟
纯虚拟析构函数
析构函数可以声明为纯虚函数,例如在需要被抽象的基类中,但没有其他可以被声明为纯虚函数的合适函数。这样的析构函数必须有一个定义,因为所有的基类析构函数总是在派生类被销毁时被调用:

  class AbstractBase {
public:
virtual〜AbstractBase()= 0;
};
AbstractBase ::〜AbstractBase(){}
class Derived:public AbstractBase {};
// AbstractBase obj; //编译器错误
Derived obj; // OK

例外:



任何其他函数,析构函数可以通过抛出异常(这通常需要明确声明为noexcept(false))(从C ++ 11开始)终止,但是如果这个析构函数恰好在栈展开,而是调用std :: terminate。
虽然std :: uncaught_exception有时可用于检测正在进行的堆栈展开,但通常认为不允许任何析构函数通过抛出异常来终止。使用此功能的一个示例是库SOCI,它依赖于某些无名临时表的析构函数抛出异常的能力。



示例:
运行此代码。

  #include< iostream> 

struct A
{
int i;

A(int i):i(i){}

〜A()
{
std :: cout< 〜a<< i<< std :: endl;
}
};

int main()
{
A a1(1);
A * p;

{//嵌套的范围
A a2(2);
p = new A(3);
} // a2超出范围

delete p; //调用a3的析构函数
}

输出:

 〜a2 
〜a3
〜a1

内容取自 http://en.cppreference。 com / w / cpp / language / destructor


Starting a new class in QT 5.4, I noticed that the second line of code had a tilda as part of it's name. Is that related to QT or C++? What does that tilda mean and what is it trying to say here?

#include "findapplications.h"

FindApplications::FindApplications()
{

}

FindApplications::~FindApplications()
{

}

EDIT: I think I know why I wasn't getting any search results. I misspelled tilde as tilda.

解决方案

A destructor is a special member function of a class that is executed whenever an object of it's class goes out of scope or whenever the delete expression is applied to a pointer to the object of that class.

A destructor will have exact same name as the class prefixed with a tilde ~ and it can neither return a value nor can it take any parameters. Destructor can be very useful for releasing resources before coming out of the program like closing files, releasing memories etc.

The destructor is called whenever an object's lifetime ends, which includes

  • program termination, for objects with static storage duration
  • thread exit, for objects with thread-local storage duration (since C++11)
  • end of scope, for objects with automatic storage duration and for temporaries whose life was extended by binding to a reference,
  • delete-expression, for objects with dynamic storage duration, end of the full expression, for nameless temporaries;
  • stack unwinding, for objects with automatic storage duration when an exception escapes their block, uncaught.

The destructor may also be called directly, e.g. to destroy an object that was constructed using placement-new or through an allocator member function such as std::allocator::destroy(), to destroy an object that was constructed through the allocator. Note that calling a destructor directly for an ordinary object, such as a local variable, invokes undefined behavior when the destructor is called again, at the end of scope.

In generic contexts, the destructor call syntax can be used with an object of non-class type; this is known as pseudo-destructor call: see member access operator.

Implicitly-declared destructor:

If no user-defined destructor is provided for a class type (struct, class, or union), the compiler will always declare a destructor as an inline public member of its class.

Deleted implicitly-declared destructor:

The implicitly-declared or defaulted destructor for class T is undefined (until C++11) defined as deleted (since C++11) if any of the following is true:

  • T has a non-static data member that cannot be destructed (has deleted or inaccessible destructor)
  • T has direct or virtual base class that cannot be destructed (has deleted or inaccessible destructors)
  • T is a union and has a variant member with non-trivial destructor. (since C++11)

The implicitly-declared destructor is virtual (because the base class has a virtual destructor) and the lookup for the deallocation function (operator delete() results in a call to ambiguous, deleted, or inaccessible function. Trivial destructor.

The destructor for class T is trivial if all of the following is true:

  • The destructor is not user-provided (meaning, it is implicitly-defined or defaulted)
  • The destructor is not virtual (that is, the base class destructor is not virtual)
  • All direct base classes have trivial destructors
  • All non-static data members of class type (or array of class type) have trivial destructors

A trivial destructor is a destructor that performs no action. Objects with trivial destructors don't require a delete-expression and may be disposed of by simply deallocating their storage. All data types compatible with the C language (POD types) are trivially destructible.

Implicitly-defined destructor:

If the implicitly-declared destructor is not deleted or trivial, it is defined (that is, a function body is generated and compiled) by the compiler. This implicitly-defined destructor has an empty body.

As with any implicitly-defined special member function, the exception specification of the implicitly-defined destructor is non-throwing unless it directly invokes a function with a different exception specification (e.g. when it must call a user-defined destructor for a member or a base subobject with a different exception specification).

Destruction sequence:

For both user-defined or implicitly-defined destructors, after the body of the destructor is executed, the compiler calls the destructors for all non-static non-variant members of the class, in reverse order of declaration, then it calls the destructors of all direct base classes in reverse order of construction (which in turn call the destructors of their members and their base classes, etc), and then, if this object is of most-derived class, it calls the destructors of all virtual bases.

Even when the destructor is called directly (e.g. obj.~Foo();), the return statement in ~Foo() does not return control to the caller immediately: it calls all those member and base destructors first.

Virtual destructors:

Deleting an object through pointer to base invokes undefined behavior unless the destructor in the base class is virtual:

class Base {
 public:
    virtual ~Base() {}
};
class Derived : public Base {};
Base* b = new Derived;
delete b; // safe

A common guideline is that a destructor for a base class must be either public and virtual or protected and nonvirtual Pure virtual destructors A destructor may be declared pure virtual, for example in a base class which needs to be made abstract, but has no other suitable functions that could be declared pure virtual. Such destructor must have a definition, since all base class destructors are always called when the derived class is destroyed:

class AbstractBase {
 public:
    virtual ~AbstractBase() = 0;
};
AbstractBase::~AbstractBase() {}
class Derived : public AbstractBase {};
// AbstractBase obj;   // compiler error
Derived obj;           // OK

Exceptions:

As any other function, a destructor may terminate by throwing an exception (this usually requires it to be explicitly declared noexcept(false)) (since C++11), however if this destructor happens to be called during stack unwinding, std::terminate is called instead. Although std::uncaught_exception may sometimes be used to detect stack unwinding in progress, it is generally considered bad practice to allow any destructor to terminate by throwing an exception. One example where this functionality is used is the library SOCI, which relies on the ability of the destructors of certain nameless temporaries to throw exceptions.

Example: Run this code.

#include <iostream>

struct A
{
    int i;

    A ( int i ) : i ( i ) {}

    ~A()
    {
        std::cout << "~a" << i << std::endl;
    }
};

int main()
{
    A a1(1);
    A* p;

    { // nested scope
        A a2(2);
        p = new A(3);
    } // a2 out of scope

    delete p; // calls the destructor of a3
}

Output:

~a2
~a3
~a1

content taken from http://en.cppreference.com/w/cpp/language/destructor

这篇关于波浪线“〜”是什么意思是什么意思在C ++?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆