为什么析构函数在“返回0”之后调用?

时间:2019-03-07 13:20:51

标签: c++ destructor

此代码:

#include <iostream>

class Base { };

class Derived : public Base
{
public:
    ~Derived()
    {
        std::cout<< "Derived dtor" << std::endl;
    }
};

int main()
{
    Derived objD;
    objD.~Derived();
    return 0;
}

打印:

Derived dtor // destructor called
Derived dtor // printed by 'return 0'

我不知道第二行从哪里来。

使用此主要功能:

int main()
{
    Derived objD;
    return 0;
}

它只打印一行。

4 个答案:

答案 0 :(得分:5)

您所拥有的是根据C ++标准的未定义行为:

按照[class.dtor]/16

  

一旦为一个对象调用了析构函数,该对象就不再存在;如果为生存期已结束(6.8)的对象调用析构函数,则行为未定义。 [示例:如果显式调用了自动对象的析构函数,并且随后以通常会隐式破坏对象的方式保留该块,则该行为是不确定的。 —结束示例] < / p>

您可以使用以下语句显式调用自动对象objD的析构函数:

objD.~Derived();

对象的隐式破坏在其作用域的结尾}处调用。

答案 1 :(得分:4)

您在堆栈上创建一个对象。该对象具有自动生命周期,由其周围范围管理。如果您手动调用析构函数,则您将执行编译器为您执行的操作,并且最终会出现未定义的行为。

答案 2 :(得分:2)

您调用析构函数,c ++在主函数之后或在不使用对象之后自动调用析构函数,然后进行析构函数调用。你做两次“免费”

答案 3 :(得分:2)

对象析构函数总是在对象超出范围时调用。这是C ++设计方式的基础部分,它启用内存安全异常,RAII等。首先手动调用析构函数对此没有任何影响,因此,如果您自己调用它,它将(很可能是UB)运行两次你可以看到。

手动调用析构函数几乎总是不正确的,并且会导致未定义的行为。一种允许的情况是,您通过“ placement new”在单独分配的内存中创建了一个对象。