c++什么时候程序不调用析构函数?

When does the program not call the destructor in c++?

代码如下:

#include <iostream>

using namespace std;

class C {
public:
    C() {i = 6; cout << "A:" << i << endl;}

    C(int i0) {i = i0; cout << "B:" << i << endl;}

    ~C() {cout << "C:" << i << endl;}
private:
    int i;
};

int main(int argc, char* argv[]) {
    cout << "X" << endl;
    C *c = new C;
    cout << "Y" << endl;
}

出于某种原因,该代码的输出是

X
A:6
Y

并且出于某种原因,一旦到达代码末尾,就永远不会调用析构函数 (C:6)。这是为什么?此代码也确实调用了析构函数:

#include <iostream>

using namespace std;

class C {
public:
    C() {i = 0; cout << "A:" << i << endl;}

    C(int i0) {i = i0; cout << "B:" << i << endl;}

    ~C() {cout << "C:" << i << endl;}
private:
    int i;
};

int main(int argc, char* argv[]) {
    cout << "X" << endl;
    C c;
    cout << "Y" << endl;
}

因为你忘了写

delete c;

如果你只是继续你的程序而不删除用 new 实例化的变量,你将导致内存泄漏。

编辑,因为您编辑了您的问题:

如果你这样写

C c;
C c{1};
C c = C{1};

您创建了一个具有自动存储持续时间的变量。一旦在退出中声明的函数(或更准确地说:一旦在退出中声明的块),它将 运行 超出范围。在这种情况下,构造函数被自动调用。

如果你写

C* c = new C{};

您创建了一个指向(新)C 的指针。指针本身具有自动存储持续时间,这意味着 c 也将 运行 超出范围。但是这个指针只保存了C类型对象的地址。而且这个对象只有在你调用delete c;时才会被删除。如果你不调用 delete,你的程序 "forgets" 对象的地址,但它不会释放内存或销毁对象。那是内存泄漏。
然而,一旦您的程序结束,所有内存都将被释放(无需调用析构函数),因此在您的小示例中您不会注意到。

需要自己直接调用析构函数的情况非常

当一个对象被销毁时,析构函数会被自动调用,无论是超出堆栈实例的范围还是 deleted 堆实例。所以你的析构函数没有被调用的事实告诉你一些事情:对象正在丢失或泄漏。

new 从堆内存中创建对象的新实例并打开一个合约,当不再需要该对象时,您将负责调用 delete 到 return 它到堆。 (或者 delete [] 如果你分配一个数组)

在您的代码中,您永远不会 delete 您创建的实例。

#include <iostream>

using namespace std;

class C {
public:
    C() : m_i(6) { cout << "A:" << m_i << endl;}

    C(int i_) : m_i(i_) { cout << "B:" << m_i << endl;}

    ~C() {cout << "C:" << m_i << endl;}
private:
    int m_i;
};

int main(int argc, char* argv[]) {
    cout << "X\n";
    C* c = new C;
    C stackC;
    cout << "Y\n";
    delete c;
    cout << "Z\n";
}

现场演示:http://ideone.com/iuZim4

当您使用 'new' 分配动态变量时,对象实例的生命周期以 1) 删除或 2) 进程终止或 3) 系统重置结束。

在您的代码中,程序在调用 'delete c;' 之前终止,因此进程不会调用 dtor。

当 OS 终止进程时,进程使用的任何动态内存都是 'reclaimed'。此 OS 'Reclaiming' 也不会调用 dtor。

并且当系统关闭或重新启动时,软件停止运行,因此不会调用dtor。

在没有析构函数调用的情况下分配对象在嵌入式系统中很常见。