精英盒子 -> 程序设计 -> C++的陷阱:堆内存中的对象,在程序执行结束后会被调用析构函数么 [打印本页]

jybox 2012-06-04 20:21

C++的陷阱:堆内存中的对象,在程序执行结束后会被调用析构函数么

标题是什么意思?
标题可能有点长,大概是这个意思,我们通过new,在堆内存上创建一个对象,例如:
A *a=new A;

然后不手动delete,那么等到程序执行结束后(main函数被返回),那么对象a的析构函数会被调用么..
  
结果到底如何?
昨天我就遇到了这个问题,我问了abreto,他说应该会被调用析构函数,但是通过我的试验,看上去并没有被调用:
#include <iostream>

class A
{
public:
    A(char *str):str(str)
    {}

    ~A()
    {
        std::cout<<str<<std::endl;
    }

    char *str;
};

int main()
{
    A *a1=new A("a1");

    A *a2=new A("a2");
    delete a2;

    A a3("a3");
}

输出是:
a2
a3

  
这在什么情况下会发生?


大体两种情况,一种是程序崩溃,一种是main函数正常被return.

程序崩溃主要就是访问了错误的内存,这时程序会直接退出,不会调用任何对象的析构函数,包括用new申请的堆内存,和在栈上的局部对象。
这可以通过下面的代码实验得到:
int main()
{
    A *a1=new A("a1");

    A a3("a3");

    int b=0/0;
}

上面这段代码没有任何输出

另一种是程序正常结束,这时,main函数中声明在栈上的局部变量会被调用析构函数(因为超出了作用域嘛),而用new申请的堆内存上的对象则不会,除非你在mian函数被return前手动delete它
  
这意味着什么?
这意味着,如果你需要在new创建的对象的析构函数中进行一些工作,例如保存数据到硬盘上,那么你必须在程序结束前手动delete它,否则它的析构函数将不会被调用


而在使用Qt的时候,你的main函数不得不这么写:
OClientCore *core;
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    core=new OClientCore;
    core->init();
    
    int retrunCode=a.exec();
    delete config;
    delete core;
    return retrunCode;
}

而不是:
OClientCore *core;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    core=new OClientCore;
    core->init();

    return a.exec();
}







jybox 2012-06-04 20:24
测试环境: linux3.0  x64     G++ 4.6.1
欢迎在其他环境下测试

abreto 2012-06-04 20:37
.




Powered by phpwind v8.7 Code ©2003-2011 phpwind
Time 0.034388 second(s),query:5 Gzip enabled