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++中临时对象的析构时机的更多相关文章

  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. 5、html的body内标签之多行文本及下拉框

    一.多行文本 <textarea name="">默认值</textarea> 二.下拉框 1.单选 <select name="city& ...

  2. python 进程和线程的区别

    1.开进程的开销远大于开线程 import time from threading import Thread from multiprocessing import Process def piao ...

  3. tcp/ip详解(转)

    与UDP不同的是,TCP提供了一种面向连接的.可靠的字节流服务.TCP协议的可靠性主要有以下几点保障: (1)应用数据分割成TCP认为最适合发送的数据块.这部分是通过“MSS”(最大数据包长度)选项来 ...

  4. Axure RP 7.0 标准教程(2)--基本介绍

    母版:用来放置一些相同元素的部件  两个页面都放入母版   一处更改 所有更改 添加图片:双击可以本地添加 ---------- 创建share.axure账号  https://share.axur ...

  5. HDU-2602 Bone Collector——01背包

    首先输入一个数字代表有n个样例 接下来的三行 第一行输入n  和  v,代表n块骨头,背包体积容量为v. 第二行输入n块骨头的价值 第三行输入n块骨头的体积 问可获得最大的价值为多少 核心:关键在于d ...

  6. Spring Boot 创建自定义的properties文件

    以IDEA2018为例,在资源文件夹上点击鼠标右键,依次选择 New -> Resource Bundle ,如下图: 在弹出的对话框中,填写properties文件的名称(不用填写.prope ...

  7. P3270 [JLOI2016]成绩比较(拉格朗日插值)

    传送门 挺神仙的啊-- 设\(f[i][j]\)为考虑前\(i\)门课程,有\(j\)个人被\(B\)爷碾压的方案数,那么转移为\[f[i][j]=\sum_{k=j}^{n-1}f[i-1][k]\ ...

  8. Python 实现简单的登录注册界面

    Python 实现简单的登录注册界面 注意:编写代码之前需要导入很重要的包 import tkinter as tk import pickle from tkinter import message ...

  9. assembly x86(nasm)串比较

    预留字符串口令,输入口令串与预留密码串比较.若匹配则显示“MATCH!CONGRATULATION”,否则显示“NOMATCH!”,并让用户重新输入,程序能对口令进行测试,但测试次数最多3次,若3次输 ...

  10. 最新的vue没有dev-server.js文件,如何进行后台数据模拟?

    最新的vue里dev-server.js被替换成了webpack-dev-conf.js 在模拟后台数据的时候直接在webpack-dev-conf.js文件中修改 第一步,在const portfi ...