所以这是代码:
#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;
}
答案 0 :(得分:10)
因为你忘了写
delete c;
如果您只是在程序中继续而不删除用new实例化的变量,则会导致内存泄漏。
编辑,因为您修改了问题:
如果你写的话
C c;
C c{1};
C c = C{1};
您创建具有自动存储持续时间的变量。一旦在退出中声明它的函数它将超出范围(或者更精确:一旦在退出时声明它的块)。在这种情况下,将自动调用构造函数。
如果你写
C* c = new C{};
你创建一个指向(新)C的指针。指针本身具有自动存储持续时间,这意味着c也将超出范围。但是指针只保存C类对象的地址。只有在调用delete c;
时才会删除此对象。如果你不打电话给删除,你的程序会忘记&#34;对象的地址,但它不释放内存或销毁对象。那是一次记忆泄漏
但是一旦程序结束,所有内存都被释放(不调用析构函数),所以在你的小例子中你不会注意到。
答案 1 :(得分:5)
非常很少需要您自己直接调用析构函数。
当一个对象被销毁时,通过超出堆栈实例的范围或者通过delete
d来获取堆实例,自动调用析构函数。因此,您的析构函数未被调用的事实告诉您一些事情:对象正在丢失或泄露。
new
从堆内存创建对象的新实例,并打开一个契约,当不再需要该对象时,您将负责调用delete
将其返回堆中。 (或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";
}
答案 2 :(得分:0)
当您使用'new'分配动态变量时,对象实例的生命周期以1)删除或2)进程终止或3)系统重置结束。
在您的代码中,程序在'delete c;'之前终止。被调用,因此进程不会调用dtor。
当操作系统终止进程时,进程使用的任何动态内存都会被“回收”。此操作系统'回收'也不会调用dtor。
当系统关闭或重启时,软件停止运行,因此不会调用dtor。
在没有析构函数调用的情况下分配对象在嵌入式系统中很常见。