http://www.cnblogs.com/chaoguo1234/archive/2013/05/12/3074425.html

c++中,临时对象一旦不需要,就会调用析构函数,释放其占有的资源;而具名对象则是与创建的顺序相反,依次调用析构函数。

c++源码:

  1. class X {
  2. public:
  3. int i;
  4. int j;
  5. ~X() {}
  6. X() {}
  7.  
  8. };
  9.  
  10. int main() {
  11. X x1;
  12. X();
  13. x1.i = 1;
  14. X x2;
  15.  
  16. }

对应的汇编码:

  1. _main PROC
  2.  
  3. ; 11 : int main() {
  4.  
  5. push ebp
  6. mov ebp, esp
  7. sub esp, 24 ; x1 临时对象 x2预留24byte空间
  8.  
  9. ; 12 : X x1;
  10.  
  11. lea ecx, DWORD PTR _x1$[ebp];获取x1对象的首地址,作为隐含参数传入构造函数
  12. call ??0X@@QAE@XZ ; x1调用构造函数
  13.  
  14. ; 13 : X();
  15.  
  16. lea ecx, DWORD PTR $T2559[ebp];获取临时对象首地址,作为隐含参数传入构造函数
  17. call ??0X@@QAE@XZ ; 为临时对象调用构造函数
  18. lea ecx, DWORD PTR $T2559[ebp];获取临时对象首地址,作为隐含参数传入析构函数
  19. call ??1X@@QAE@XZ ; 为临时对象调用析构函数
  20.  
  21. ; 14 : x1.i = 1;
  22.  
  23. mov DWORD PTR _x1$[ebp], 1;将1写给x1首地址处内存,即将1写入x1中的成员变量i
  24.  
  25. ; 15 : X x2;
  26.  
  27. lea ecx, DWORD PTR _x2$[ebp];获取x2的首地址,作为隐含参数传入构造函数
  28. call ??0X@@QAE@XZ ; x2调用构造函数
  29.  
  30. ; 16 :
  31. ; 17 :
  32. ; 18 : }
  33.  
  34. lea ecx, DWORD PTR _x2$[ebp];获取x2的首地址,作为隐含参数传入析构函数
  35. call ??1X@@QAE@XZ ; x2调用析构函数
  36. lea ecx, DWORD PTR _x1$[ebp];获取x1的首地址,作为隐含参数传入析构函数
  37. call ??1X@@QAE@XZ ; x1调用析构函数
  38. xor eax, eax
  39. mov esp, ebp
  40. pop ebp
  41. ret 0
  42. _main ENDP

从上面的汇编码可以看出,临时对象确实是在不需要之后就调用了析构函数,尽管它在x2对象之前被创建,但依然在x2对象之前被析构。而x1 x2析构函数调用顺序,是与他们构造函数的调用顺序相反。

再看下面的情况:

c++中的源码:

  1. class X {
  2. public:
  3. int i;
  4. int j;
  5. int k;
  6. X() {}
  7. ~X() {}
  8. };
  9.  
  10. int main() {
  11. X x1;
  12. X(), x1.i = 1;//这里有一条逗号运算符
  13. X x2;
  14. }

这里,改造临时对象之后,有一个逗号表达式,而不是分号。

下面是汇编码:

  1. ; 12 : int main() {
  2.  
  3. push ebp
  4. mov ebp, esp
  5. sub esp, 36 ; x1 临时对象 x2预留36字节的空间
  6.  
  7. ; 13 : X x1;
  8.  
  9. lea ecx, DWORD PTR _x1$[ebp];获取x1的的首地址,作为隐含参数传递给构造函数
  10. call ??0X@@QAE@XZ ; x1调用构造函数
  11.  
  12. ; 14 : X(), x1.i = 1;//这里有一条逗号运算符
  13.  
  14. lea ecx, DWORD PTR $T2560[ebp];获取临时对象的首地址,作为隐含参数传递给构造函数
  15. call ??0X@@QAE@XZ ; 为临时对象调用构造函数
  16. mov DWORD PTR _x1$[ebp], 1;将1赋给x1首地址处的内存,即给x1的成员变量i赋值1
  17. lea ecx, DWORD PTR $T2560[ebp];获取临时变量的首地址,作为隐含参数传递给析构函数
  18. call ??1X@@QAE@XZ ; 为临时对象调用析构函数
  19.  
  20. ; 15 : X x2;
  21.  
  22. lea ecx, DWORD PTR _x2$[ebp];获取x2的首地址,作为隐含参数传递给构造函数
  23. call ??0X@@QAE@XZ ; x2调用构造函数
  24.  
  25. ; 16 : }
  26.  
  27. lea ecx, DWORD PTR _x2$[ebp];获取x2的首地址,作为隐含参数传递给析构函数
  28. call ??1X@@QAE@XZ ; x2调用析构函数
  29. lea ecx, DWORD PTR _x1$[ebp];获取x1的首地址,作为隐含参数传递给析构函数
  30. call ??1X@@QAE@XZ ; x1调用析构函数
  31. xor eax, eax
  32. mov esp, ebp
  33. pop ebp
  34. ret 0
  35. _main ENDP

可以看到,与第一次不同的是,临时对象构造完毕之后,并没有立即调用析构函数,而是执行了逗号后面的赋值语句后,才调用的析构函数。

综上所述:

临时对象调用析构函数的时机是一条高级语言执行完毕的时候,而一条高级语言执行完毕的标志是分号。所以,临时对象调用析构函数的时机是碰到分号的时候

从汇编看c++中临时对象的析构时机的更多相关文章

  1. 从汇编看c++中全局对象和全局变量

    先来看c++源码: #include <iostream> using namespace std; class X { public: int i; public: X() : i(ii ...

  2. 从汇编看c++中指向成员变量的指针(二)

    在从汇编看c++中指向成员变量的指针(一)中讨论的情形没有虚拟继承,下面来看看,当加入了虚拟继承的时候,指向成员变量的指针有什么变化. 下面是c++源码: #include <iostream& ...

  3. [转] C++中临时对象及返回值优化

    http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...

  4. 转:C++中临时对象及返回值优化

    http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...

  5. 从汇编看c++中的多态

    http://www.cnblogs.com/chaoguo1234/archive/2013/05/19/3079078.html 在c++中,当一个类含有虚函数的时候,类就具有了多态性.构造函数的 ...

  6. C++中临时对象的学习笔记

    http://www.cppblog.com/besterChen/category/9573.html 所属分类: C/C++/STL/boost  在函数调用的时候,无论是参数为对象还是返回一个对 ...

  7. 从 php 源码看 php 中的对象

    从一个简单的例子说起: class Person { public $name; public $age; public function __construct($name, $age) { $th ...

  8. 从汇编看c++中含有虚基类对象的析构

    c++中,当继承结构中含有虚基类时,在构造对象时编译器会通过将一个标志位置1(表示调用虚基类构造函数),或者置0(表示不调用虚基类构造函数)来防止重复构造虚基类子对象.如下图菱形结构所示: 当构造类B ...

  9. 从汇编看c++中指向成员变量的指针(一)

    在c++中,指向类成员变量的指针存储的并不是该成员变量所在内存的地址,而仅仅是该成员变量在该类对象中相对于对象首地址的偏移量.因此,它必须绑定到某一个对象或者对象指针上面,这里的对象和对象指针,就相当 ...

随机推荐

  1. Coding WebIDE 开放支持第三方 Git 仓库

    为了给开发者提供更多便捷的开发方式,Coding.net 现正式宣布 WebIDE 开放啦 ! 用户可以自由选择各大代码托管平台,推送代码到其它家代码仓库啦,同时新版的 WebIDE 还有如下特性: ...

  2. Flutter实战视频-移动电商-49.详细页_Stack制作底部工具栏

    49.详细页_Stack制作底部工具栏 一直悬浮在最下面的 Stack层叠组件.里面用Row 可以横向布局 开始 stack如果想定位就要用position去定位. 修改return返回值的这个地方 ...

  3. 解决At least one JAR was scanned for TLDs yet contained no TLDs. 问题

    启动tomcat运行项目时,总是提示: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug loggin ...

  4. UVa 10891 Game of Sum (DP)

    题意:给定一个长度为n的整数序列,两个人轮流从左端或者右端拿数,A先取,问最后A的得分-B的得分的结果. 析:dp[i][j] 表示序列 i~j 时先手得分的最大值,然后两种决策,要么从左端拿,要么从 ...

  5. E20181001-ts

    decorate vt. 装饰; 点缀; 粉刷; 授予(某人)勋章  vi. 装饰; 布置;

  6. IOS11 - UINavigationItem大标题,搜索栏实现

    1.新建模型 class Contact: NSObject { var name : String? var mobile : String?{ didSet{ { mobileString = m ...

  7. vue key值的重复键问题报错

    1.问题描述:在vue2.0+ 中做一个公用的评论组件,:key使用的时创建评论的时间,当加载更多的时候,会报错: Duplicate keys detected: '2019-01-24T07:15 ...

  8. IT行业技术及程序员相关网站荟萃

    最近我花了一些时间收集了一些与自己工作相关的常用的网址,由于时间关系,暂时只是收集了这么多,以后有时间再随时添加. 1.程序员网址导航pg265 http://www.pg265.com/TNT程序网 ...

  9. IT兄弟连 JavaWeb教程 Servlet会话跟踪 Session常用方法

    ●  public Object getAttribute(String name) 该方法返回在该session会话中具有指定名称的对象,如果没有指定名称的对象,则返回null. ●  public ...

  10. 商务系统的构造思路(无源码!)+如何用jsp实现点击单选框内容显示在另一个jsp页面

    敲码经验总结: 之前犯了一个错误就是,没有从底层开始学起,有啥问题,就直接博客园找源码,去CSDN找源代码,看到代码就复制粘贴,结果从新梳理知识点的时候,貌似除了复制粘贴,印象深刻的知识啥也没学到. ...