从汇编看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++中,指向类成员变量的指针存储的并不是该成员变量所在内存的地址,而仅仅是该成员变量在该类对象中相对于对象首地址的偏移量.因此,它必须绑定到某一个对象或者对象指针上面,这里的对象和对象指针,就相当 ...
随机推荐
- vsftpd总结
1 vsftps配置文件详解 (1)/user/sbin/vsftpd 主程序 (2)/etc/rc.d/init.d/vsftpd 启动脚本 (3)/etc/pam.d/vsftpd (file= ...
- JQuery点击table获取点击行的数据
$(function () {var TaskType = '';$("#data_table tr:gt(0)").click(function () { TaskType = ...
- CodeForces水题
CodeForces754A 题意: 给一个数组,让你变成1-n,输出变换区间,要求原区间和不为0. 思路: 如果原数组不为0,那就是YES: 如果为0,则从1开始扫过去,碰到不为0时,分两个区间[1 ...
- POJ3268【最短路】
题意: n个点m条有向边,每个点有一头牛,每头牛会沿着各自的最短路先到x点,然后又从x点到各自的点,求这些牛中间最短路程最大的牛. 思路: 从x点到各点的最短路不用说了,裸的最短路: 但是从所有点到x ...
- [Xcode 实际操作]一、博主领进门-(12)代码重构
目录:[Swift]Xcode实际操作 本文将演示如何重构代码. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] [快速更改同名变量或常量] 在代码编辑区域,点击需 ...
- 原来TextBox打开了MultiLine之后就不能使用AutoComplete了
private void Form1_Load(object sender, EventArgs e) { // Create the list to use as the custom source ...
- PostgreSQL-10-数据运算与函数
1.算数运算符 SELECT 5+5; 加法 SELECT 10-5; 减法 SELECT 2*3; 乘法 SELECT 10.0/3; 除法 SELECT 10%7; 取余数 SELE ...
- css实现发光的input输入框
效果图截图: 案例代码示下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- Zynq7000开发系列-5(OpenCV开发环境搭建:Ubuntu、Zynq)
操作系统:Ubuntu14.04.5 LTS 64bit OpenCV:OpenCV 3.1.0.opencv_contrib gcc:gcc version 4.8.4 (Ubuntu 4.8.4- ...
- UWP 画一个圆形头像
经常需要做一个圆形头像的样式,like this 做法很简单,直接上xaml. <Ellipse Width=" Height="> <Ellipse.Fill& ...