从汇编看c++中临时对象的析构时机
http://www.cnblogs.com/chaoguo1234/archive/2013/05/12/3074425.html
c++中,临时对象一旦不需要,就会调用析构函数,释放其占有的资源;而具名对象则是与创建的顺序相反,依次调用析构函数。
c++源码:

- class X {
- public:
- int i;
- int j;
- ~X() {}
- X() {}
- };
- int main() {
- X x1;
- X();
- x1.i = 1;
- X x2;
- }

对应的汇编码:

- _main PROC
- ; 11 : int main() {
- push ebp
- mov ebp, esp
- sub esp, 24 ; 为x1 临时对象 x2预留24byte空间
- ; 12 : X x1;
- lea ecx, DWORD PTR _x1$[ebp];获取x1对象的首地址,作为隐含参数传入构造函数
- call ??0X@@QAE@XZ ; 为x1调用构造函数
- ; 13 : X();
- lea ecx, DWORD PTR $T2559[ebp];获取临时对象首地址,作为隐含参数传入构造函数
- call ??0X@@QAE@XZ ; 为临时对象调用构造函数
- lea ecx, DWORD PTR $T2559[ebp];获取临时对象首地址,作为隐含参数传入析构函数
- call ??1X@@QAE@XZ ; 为临时对象调用析构函数
- ; 14 : x1.i = 1;
- mov DWORD PTR _x1$[ebp], 1;将1写给x1首地址处内存,即将1写入x1中的成员变量i中
- ; 15 : X x2;
- lea ecx, DWORD PTR _x2$[ebp];获取x2的首地址,作为隐含参数传入构造函数
- call ??0X@@QAE@XZ ; 为x2调用构造函数
- ; 16 :
- ; 17 :
- ; 18 : }
- lea ecx, DWORD PTR _x2$[ebp];获取x2的首地址,作为隐含参数传入析构函数
- call ??1X@@QAE@XZ ; 为x2调用析构函数
- lea ecx, DWORD PTR _x1$[ebp];获取x1的首地址,作为隐含参数传入析构函数
- call ??1X@@QAE@XZ ; 为x1调用析构函数
- xor eax, eax
- mov esp, ebp
- pop ebp
- ret 0
- _main ENDP

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

- class X {
- public:
- int i;
- int j;
- int k;
- X() {}
- ~X() {}
- };
- int main() {
- X x1;
- X(), x1.i = 1;//这里有一条逗号运算符
- X x2;
- }

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

- ; 12 : int main() {
- push ebp
- mov ebp, esp
- sub esp, 36 ; 为x1 临时对象 x2预留36字节的空间
- ; 13 : X x1;
- lea ecx, DWORD PTR _x1$[ebp];获取x1的的首地址,作为隐含参数传递给构造函数
- call ??0X@@QAE@XZ ; 为x1调用构造函数
- ; 14 : X(), x1.i = 1;//这里有一条逗号运算符
- lea ecx, DWORD PTR $T2560[ebp];获取临时对象的首地址,作为隐含参数传递给构造函数
- call ??0X@@QAE@XZ ; 为临时对象调用构造函数
- mov DWORD PTR _x1$[ebp], 1;将1赋给x1首地址处的内存,即给x1的成员变量i赋值1
- lea ecx, DWORD PTR $T2560[ebp];获取临时变量的首地址,作为隐含参数传递给析构函数
- call ??1X@@QAE@XZ ; 为临时对象调用析构函数
- ; 15 : X x2;
- lea ecx, DWORD PTR _x2$[ebp];获取x2的首地址,作为隐含参数传递给构造函数
- call ??0X@@QAE@XZ ; 为x2调用构造函数
- ; 16 : }
- lea ecx, DWORD PTR _x2$[ebp];获取x2的首地址,作为隐含参数传递给析构函数
- call ??1X@@QAE@XZ ; 为x2调用析构函数
- lea ecx, DWORD PTR _x1$[ebp];获取x1的首地址,作为隐含参数传递给析构函数
- call ??1X@@QAE@XZ ; 为x1调用析构函数
- xor eax, eax
- mov esp, ebp
- pop ebp
- ret 0
- _main ENDP

可以看到,与第一次不同的是,临时对象构造完毕之后,并没有立即调用析构函数,而是执行了逗号后面的赋值语句后,才调用的析构函数。
综上所述:
临时对象调用析构函数的时机是一条高级语言执行完毕的时候,而一条高级语言执行完毕的标志是分号。所以,临时对象调用析构函数的时机是碰到分号的时候
从汇编看c++中临时对象的析构时机的更多相关文章
- 从汇编看c++中全局对象和全局变量
先来看c++源码: #include <iostream> using namespace std; class X { public: int i; public: X() : i(ii ...
- 从汇编看c++中指向成员变量的指针(二)
在从汇编看c++中指向成员变量的指针(一)中讨论的情形没有虚拟继承,下面来看看,当加入了虚拟继承的时候,指向成员变量的指针有什么变化. 下面是c++源码: #include <iostream& ...
- [转] C++中临时对象及返回值优化
http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...
- 转:C++中临时对象及返回值优化
http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...
- 从汇编看c++中的多态
http://www.cnblogs.com/chaoguo1234/archive/2013/05/19/3079078.html 在c++中,当一个类含有虚函数的时候,类就具有了多态性.构造函数的 ...
- C++中临时对象的学习笔记
http://www.cppblog.com/besterChen/category/9573.html 所属分类: C/C++/STL/boost 在函数调用的时候,无论是参数为对象还是返回一个对 ...
- 从 php 源码看 php 中的对象
从一个简单的例子说起: class Person { public $name; public $age; public function __construct($name, $age) { $th ...
- 从汇编看c++中含有虚基类对象的析构
c++中,当继承结构中含有虚基类时,在构造对象时编译器会通过将一个标志位置1(表示调用虚基类构造函数),或者置0(表示不调用虚基类构造函数)来防止重复构造虚基类子对象.如下图菱形结构所示: 当构造类B ...
- 从汇编看c++中指向成员变量的指针(一)
在c++中,指向类成员变量的指针存储的并不是该成员变量所在内存的地址,而仅仅是该成员变量在该类对象中相对于对象首地址的偏移量.因此,它必须绑定到某一个对象或者对象指针上面,这里的对象和对象指针,就相当 ...
随机推荐
- Coding WebIDE 开放支持第三方 Git 仓库
为了给开发者提供更多便捷的开发方式,Coding.net 现正式宣布 WebIDE 开放啦 ! 用户可以自由选择各大代码托管平台,推送代码到其它家代码仓库啦,同时新版的 WebIDE 还有如下特性: ...
- Flutter实战视频-移动电商-49.详细页_Stack制作底部工具栏
49.详细页_Stack制作底部工具栏 一直悬浮在最下面的 Stack层叠组件.里面用Row 可以横向布局 开始 stack如果想定位就要用position去定位. 修改return返回值的这个地方 ...
- 解决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 ...
- UVa 10891 Game of Sum (DP)
题意:给定一个长度为n的整数序列,两个人轮流从左端或者右端拿数,A先取,问最后A的得分-B的得分的结果. 析:dp[i][j] 表示序列 i~j 时先手得分的最大值,然后两种决策,要么从左端拿,要么从 ...
- E20181001-ts
decorate vt. 装饰; 点缀; 粉刷; 授予(某人)勋章 vi. 装饰; 布置;
- IOS11 - UINavigationItem大标题,搜索栏实现
1.新建模型 class Contact: NSObject { var name : String? var mobile : String?{ didSet{ { mobileString = m ...
- vue key值的重复键问题报错
1.问题描述:在vue2.0+ 中做一个公用的评论组件,:key使用的时创建评论的时间,当加载更多的时候,会报错: Duplicate keys detected: '2019-01-24T07:15 ...
- IT行业技术及程序员相关网站荟萃
最近我花了一些时间收集了一些与自己工作相关的常用的网址,由于时间关系,暂时只是收集了这么多,以后有时间再随时添加. 1.程序员网址导航pg265 http://www.pg265.com/TNT程序网 ...
- IT兄弟连 JavaWeb教程 Servlet会话跟踪 Session常用方法
● public Object getAttribute(String name) 该方法返回在该session会话中具有指定名称的对象,如果没有指定名称的对象,则返回null. ● public ...
- 商务系统的构造思路(无源码!)+如何用jsp实现点击单选框内容显示在另一个jsp页面
敲码经验总结: 之前犯了一个错误就是,没有从底层开始学起,有啥问题,就直接博客园找源码,去CSDN找源代码,看到代码就复制粘贴,结果从新梳理知识点的时候,貌似除了复制粘贴,印象深刻的知识啥也没学到. ...