一般我们都知道构造和析构的次序:

构造从类层次的最根处开始,在每一层中,首先调用基类的构造函数,然后调用成员对象的构造函数。析构则严格按照与构造相反的次序执行,该次序是唯一的,否则编译器将无法自动执行析构过程。

构造函数和析构函数都是由编译器隐式调用的。这些函数的调用顺序取决于程序的执行进入和离开实例化对象时所在的那个作用域的顺序。一般而言,析构函数的调用顺序和构造函数的调用顺序相反,但是,对象的存储类可以改变析构函数的调用顺序。

  • 对于在全局作用域中定义的对象,它们的构造函数是在文件中所有其他函数(包括main)开始执行之前被调用的(但无法保证不同文件的全局对象构造函数的执行顺序)。对应的析构函数是在终止main之后调用的
  • exit函数会迫使程序立即终止,而不会执行自动对象的析构函数。这个函数经常用来在检测到输入错误或者程序所处理的文件无法打开时终止程序。
  • abort函数与exit函数功能相似,但它会迫使程序立即终止,而不允许调用任何对象的析构函数。abort函数通常用来表明程序的非正常终止。
  • 自动局部变量的构造函数是在程序的执行到达定义这个对象的位置时调用的,而对应的析构函数是在程序离开这个对象的作用域时调用的(即定义这个对象的代码完成了执行)。每次执行进入和离开自动对象的作用域时,都会调用它的构造函数和析构函数。如果程序调用了exit或abort函数而终止,则不会调用自动对象的析构函数。
  • 静态局部对象的析构函数只调用一次,即执行首次到达定义这个对象的位置时。对应的析构函数是在main终止或程序调用exit函数时调用的。
  • 全局对象和静态对象是以创建它们时相反的顺序销毁的。如果程序由于调用了exit函数而终止,则不会调用静态对象的析构函数。

析构函数在下边3种情况时被调用:

  1. 对象生命周期结束,被销毁时;
  2. delete指向对象的指针时,或delete指向对象的基类类型指针,而其基类虚构函数是虚函数时;
  3. 对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。

1、例1

#include<iostream.h>
class A{public:A(){cout<<"constructing A"<<endl;}     ~A(){cout<<"destructing A"<<endl;}private:int a;
};
class B: public A{public:B(){cout<<"constructing B"<<endl;}~B(){cout<<"destructing B"<<endl;}private:int b;
};void main(){B b;
}

运行结果为:

constructing A
constructing B
destructing B
destructing A

上述代码还说明了一件事:析构函数的调用顺序与构造函数的调用顺序相反。

2、例2

例子2则正好说明了为什么基类应该把析构函数声明为虚函数,请先看下边的例子:

#include<iostream.h>
class A{public:A(){cout<<"constructing A"<<endl;} ~A(){cout<<"destructing A"<<endl;}private:int a;
};
class B: public A{public:B(){cout<<"constructing B"<<endl;}~B(){cout<<"destructing B"<<endl;}private:int b;
};void main(){A* a = new B;delete a;
}

运行结果为:

constructing A
constructing B
destructing A

若将class A中的析构函数声明为虚函数,运行结果将变成:

constructing A
constructing B
destructing B
destructing A

3、例3

#include<iostream.h>
class A{public:A(){cout<<"constructing A"<<endl;}~A(){cout<<"destructing A"<<endl;}private:int a;
};class C{public:C(){cout<<"constructing C"<<endl;}~C(){cout<<"destructing C"<<endl;}private:int c;
};class B:public A{public:B(){cout<<"constructing B"<<endl;}~B(){cout<<"destructing B"<<endl;}private:int b;C c;
};void main()
{B b;
}

运行结果为:

constructing A
constructing C
constructing B
destructing B
destructing C
destructing A

b的析构函数调用之后,又调用了b的成员c的析构函数,同时再次验证了析构函数的调用顺序与构造函数的调用顺序相反。

若将上边的代码中的main()函数内容改成

 A* a = new B;delete a;

由例2我们知道,这样class B的析构函数不会被调用,所以class C的析构函数也不会被调用。
正如我们想的,运行结果为:

constructing A
constructing C
constructing B
destructing A

原文链接:

https://blog.csdn.net/weizhee/article/details/562833

https://blog.csdn.net/feitianxuxue/article/details/7323054

C++析构函数何时被调用相关推荐

  1. 构造函数、拷贝构造函数和析构函数的的调用时刻及调用顺序

    构造函数.拷贝构造函数和析构函数的的调用时刻及调用顺序 对象是由"底层向上"开始构造的,当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达 ...

  2. vector用erase删除元素时,为什么被删元素的析构函数会被调用更多次?

    vector用erase删除元素时,为什么被删元素的析构函数会被调用更多次? 分类: C++2011-08-18 14:55 720人阅读 评论(0) 收藏 举报 vectoriteratorexce ...

  3. 也谈析构:析构函数何时被调用

    为什么要说"也"?用google搜索"析构函数"是,google会说"约有81,500项符合 析构函数 的查询结果",我最近复习c++是有所 ...

  4. php中析构函数是自动调用吗,php析构函数什么时候调用

    析构函数何时被调用 析构函数在下边3种情况时被调用: 对象生命周期结束,被销毁时: 主动调用delete :(推荐学习:PHP编程从入门到精通) 对象i是对象o的成员,o的析构函数被调用时,对象i的析 ...

  5. php析构函数什么时候调用?

    析构函数何时被调用 析构函数在下边3种情况时被调用: 对象生命周期结束,被销毁时: 主动调用delete :(推荐学习:PHP编程从入门到精通) 对象i是对象o的成员,o的析构函数被调用时,对象i的析 ...

  6. C++ 析构函数何时被调用?

    参考文章1:C++ 什么时候调用析构函数 参考文章2:析构函数何时被调用 文章目录 析构函数何时会被调用? 第一种 生命周期结束(在栈区创建的对象,生命周期结束时,会自动执行析构函数) 第二种 del ...

  7. C++析构函数的自动调用问题

    首先要明确一点,系统只会自动释放栈内空间,而堆内空间需要用户自己维护. C++中,除了new来的空间存放在堆内,其他均存放在栈中. 当单纯的创建对象的时候,对象存放在栈中,此时在程序块的}后面,系统会 ...

  8. C++继承中析构函数 构造函数的调用顺序以及虚析构函数

    首先说说构造函数.大家都知道构造函数里就能够调用成员变量,而继承中子类是把基类的成员变成自己的成员,那么也就是说子类在构造函数里就能够调用基类的成员了,这就说明创建子类的时候必须先调用基类的构造函数, ...

  9. 析构函数什么时候调用

    在这个对象的作用域最后..比如你在main里面声明了一个类A..那么~A()会在main结束时调用.. 如果在自定义的函数f()里面声明了一个A 函数f结束的时候就会调用~A()或者你delete 指 ...

最新文章

  1. 数据结构与算法实验祝恩_《数据结构与算法》实验教学大纲
  2. 打开完成查看的CAD图纸如何一键进行打印?
  3. python3教程-终于清楚python3详细教程
  4. 《Adobe Flash Professional CC经典教程》——1.13 查找关于使用Flash的资源
  5. CTFshow 命令执行 web52
  6. wxWidgets:VScroll示例
  7. java性能调优及问题追踪--Btrace的使用
  8. JavaScript中发布/订阅模式的理解
  9. 李宏毅机器学习(五)Transformer
  10. SpringAOP Aspect注解实现简单日志功能
  11. NULL指针的奇妙之旅
  12. mysql5_MySQL5.5下载-MySQL数据库5.5下载 v5.5.60.1官方版(32位/64位)--pc6下载站
  13. 入侵检测系统原理和实现
  14. 常用论文检查语法错误软件和网址
  15. 【Unity3D_常用模块】 Socket网络模块(超级详细完整,上线项目中稳定使用着)
  16. Android集成bugly实现异常上报
  17. Microsoft Office 历史版本
  18. 如何提高公众号的打开率、分享率?
  19. React-router(8)Link 标签 to 属性为对象时(路由信息传值)
  20. 预告 · 5月26日IGS大会腾讯云游戏新文娱分论坛遇见TcaplusDB

热门文章

  1. Ubuntu 使用play命令播放音乐 mp3 wav 等文件
  2. 对不起,我只过1%梦想生活
  3. mysql truncated_mysql中出现的Data truncated for column
  4. 9 款必装Windows软件,你爱上了哪一款!
  5. 学生党平价无线蓝牙耳机推荐,2022性价比高的无线蓝牙耳机品牌推荐
  6. Hystrix中的HystrixRuntimeException错误
  7. 无损音频wav音乐格式怎么转换成mp3格式 1
  8. 环形缓冲区实现(C语言)
  9. 如何考取 AWS 技术认证
  10. UPS功率计算及分类