假期 2020.02.04

慕课学习资源



定义

  • 名字与类名相同,在前面加“~”即可,与构造函数一样,没有返回值,但是有参数,并且一个类中最多一个析构函数。
  • 析构函数在对象消亡之后自动被调用,常用来释放空间
  • 编译器通常会自动生成缺省的析构函数,与确实缺省构造函数类似,实际上什么都不做
  • 如果定义了,则编译器不生成缺省析构函数

运用示例

其中创建一个对象数组,一共三个对象,三个对象在程序结束后自动调用析构函数


常出现情况

  1. delete 运算导致析构函数调用。
  2. 若new一个对象数组,那么用delete释放时应该写 []。否则只delete一个对象(调用一次析构函数)
  3. 析构函数在对象作为函数返回值返回后被调用,函数调用返回时生成临时对象返回

分析:在return a之后,子函数中的对象消亡,调用第一次析构函数;在主函数结束之后,主函数中的实参消亡,进行调用第二次析构函数。
对比下例:

分析: 在return a之后,子函数中的对象消亡,调用第一次析构函数;函数调用的返回值(临时对象)用过后,该临时对象析构函数被调用,进行调用第二次析构函数;第三次定义的全局对象消亡,调用析构函数。


析构函数调用顺序

在网上扒的一段代码

#include <iostream>
#include <string>
using namespace std;class Demo {public:Demo(string s);~Demo();
private:string m_s;
};
Demo::Demo(string s) : m_s(s) { }
Demo::~Demo() { cout << m_s << endl; }void func() {//局部对象Demo obj1("1");
}//全局对象
Demo obj2("2");int main() {//局部对象Demo obj3("3");//new创建的对象Demo* pobj4 = new Demo("4");func();cout << "main" << endl;return 0;
}

执行效果

分析:发现全局对象是最后调用析构函数的;最先是局部对象;
理论原因:

  • 在函数内部创建的对象是局部对象,位于栈区,函数执行结束时会调用这些对象的析构函数。
  • new 创建的对象位于堆区,通过 delete 删除时才会调用析构函数;如果没有 delete,析构函数就不会被执行。
  • 在所有函数之外创建的对象是全局对象,位于内存分区中的全局数据区,程序在结束执行时会调用这些对象的析构函数,并且是最后调用的,
    如下图

    我们会发现全局变量确实按照栈的顺序进行调用析构函数的,后入先出。其实全局对象与局部对象都是按照如此的方式进行调用析构函数顺序,只要是以栈的形式分配空间。但这个也与程序的执行有关,从上到下的顺序。
    附:
    栈: 在 windows 下,栈是向低地址扩展的数据结构,是一块连续的内存区域,栈顶的地址和栈的最大容量是系统预先规定好的,能从栈获得的空间较小。
    :堆是向高地址扩展的数据结构,是不连续的内存区域,这是由于系统是由链表在存储空闲内存地址,自然堆就是不连续的内存区域,且链表的遍历也是从低地址向高地址遍历的,堆得大小受限于计算机系统的有效虚拟内存空间,由此空间,堆获得的空间比较灵活,也比较大。

举一个慕课上面的例子

#include<iostream>
using namespace std;
class Demo {int id;
public: Demo(int i){id = i; cout << "id=" << id << " constructed" << endl;}~Demo() {cout << "id=" << id << " destructed" << endl;}
};
Demo d1(1);
void Func() {static Demo d2(2); Demo d3(3); cout << "func" << endl;
}
int main() {Demo d4(4); d4 = 6; cout << "main" << endl; Demo d5(5);Func(); cout << "main ends" << endl; return 0;
}

执行结果

  1. 对应全局对象Demo d1(1);
id=1 constructed
  1. 对应局部变量Demo d4(4);
id=4 constructed
  1. 临时对象d4 = 6;
id=6 constructed
id=6 destructed
main
  1. 对应局部变量Demo d5(5);
id=5 constructed
  1. 两个局部对象
    static Demo d2(2); Demo d3(3);
id=2 constructed
id=3 constructed
func
  1. 子函数返回,调用析构函数.静态局部对象见后续分析
id=3 destructed
main ends
  1. 主函数中的两个局部对象,调用析构函数
id=5 destructed
id=6 destructed
  1. 剩下全局对象和局部对象。而全局变量和静态局部变量时从静态存储区中划分的空间,即栈,二者的区别在于作用域的不同,全局变量作用域大于静态局部变量(只用于声明它的函数中),而之所以是先释放 2 在释放 1的原因是, 程序中首先调用的是 1的构造函数,然后调用的是 2 的构造函数,析构函数的调用与构造函数的调用顺序刚反。
id=2 destructed
id=1 destructed

复制构造函数与析构函数的例子

c++ -- 析构函数相关推荐

  1. Object的finalize()方法的作用是否与C++的析构函数作用相同

    Object的finalize()方法的作用是否与C++的析构函数作用相同 public class Finalization {private static Finalization finaliz ...

  2. 基类的析构函数为什么要设置成virtual

    今天在一场面试过程中碰到这个问题,当时一时片刻没有反应过来,一头雾水.只记得自己回到说,是会造成内存泄露,但面试穷追猛打,一直追问为什么造成内存泄露,还给举例说明,一般情况下是不会造成内存泄露的,搞得 ...

  3. C++ 析构函数(函数前面有波浪号~)

    什么是析构函数 析构函数定义类型和构造函数的定义类型差不多, 也是名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数.析构函数有助于在跳出程序(比如 ...

  4. C++ 笔记(17)— 类和对象(构造函数、析构函数、拷贝构造函数)

    1. 构造函数 构造函数是一种特殊的函数(方法),在根据类创建对象时被调用.构造函数是一种随着对象创建而自动被调用的函数,它的主要用途是为对象作初始化. 构造函数的名称与类的名称是完全相同的,并且不会 ...

  5. php构造和析构方法,php5构造函数与析构函数实例

    自php5起,有了构造函数与析构函数. 这使得php更富有面向对象的魅力了. 在php4时,构造函数用的是与类同名的函数来进行构造这个动作. 例如: 复制代码 代码示例: /* * myclass.p ...

  6. 【C++】多态(早期绑定、后期绑定)、抽象类(纯虚函数)、虚析构函数

    我们都知道面向对象编程的三大特征是封装.继承.多态,今天我们就来说一下其中之一的多态. 概念: 多态: 多态字面意思就是多种形态,C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同 ...

  7. 对象特性-构造函数和析构函数

    基础概念: 构造函数:是一种特殊的方法.主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或 ...

  8. 在析构函数中delete this指针问题

    思考:在析构函数中delete this指针,运行下面代码会产生什么样的结果呢? #include <iostream> using namespace std; class A{ pub ...

  9. 【C++】浅析析构函数(基类中)为什么要写成虚基类?

    为什么有了虚析构函数,就能先调用子类的析构函数? class A {virtual ~A(){} };class B : A {virtual ~B(){} };A *p = new B(); del ...

  10. php析构函数的用法

    简单的说,析构函数是用来在对象关闭时完成的特殊工作,比如我写的上例,在实例化同时打开某文件,但是它什么时候关闭呢,用完就关闭呗,所以析构函数直接关闭它, 又或者在析构时,我们将处理好的某些数据一并写进 ...

最新文章

  1. Hibernate QBC 分页
  2. Android签名机制之---签名验证过程详解
  3. 028_CSS外边距
  4. arcgis 出图背景_ArcGIS空间制图分析视频教程(二狮兄出品)含ArcMap
  5. r语言error in match.fun(fun) :_Go语言200行写区块链源代码分析
  6. youleb多风格响应式博客wordpress主题模板
  7. java 防止js注入_在WebView中如何让JS与Java安全地互相调用
  8. android开启热点softap模式,[RK3288][Android6.0] Wifi开启热点(SoftAP)流程小结
  9. 2020年Java学习计划祝大家新年快乐
  10. python制作词云图设置停用词,Python生成词云图
  11. 递归算法设计 —— 选择排序和冒泡排序
  12. 人生五大投资,你投对了几个?
  13. 奶块最新服务器叫什么,奶块5.4.0版本更新公告
  14. 简述 Erasure Code,EC 纠删码原理
  15. 【笔记】分布式网络与分布式账本
  16. 什么是NLP,NLP主要有什么用,为什么要学自然语言处理?
  17. 以阿里IoT开发物联网和应用平台
  18. win10解决桌面图标变白
  19. 【初始C语言】——(5)
  20. 第一课行列式性质与几何意义

热门文章

  1. Android Vlc播放器加载rtsp及http地址视频
  2. ACM期刊LaTex模板使用
  3. 2017年薪资满意度白皮书:五年内月薪不过万太慢!
  4. python实战故障诊断之CWRU数据集(四):线性回归模型的应用
  5. 笔记 - 高等教育的创新
  6. 12对胸椎对应体表标志_胸部检查第一节胸部的体表标志与常用标记线
  7. Android 高德地图升级9.2.0版本问题
  8. Linux 认识系统服务(daemon)
  9. 2020年第二届“网鼎杯”网络安全大赛 白虎组 部分题目Writeup
  10. FileProvider无法获取外置SD卡问题解决方案 | Failed to find configured root that contains