一、原码分析
1.1 测试代码

为了方便查看拷贝构造函数调用过程,自定义了拷贝构造函数,但啥也没干。

class CTEST
{
public:
int m_nData; //Method:
public:
CTEST()
{
printf("0x%p CTEST is constructed\n", this);
} CTEST(CTEST& oCtest)
{
printf("0x%p CTEST copy constructor is called, copy object from 0x%p\n", this, &oCtest);
} ~CTEST()
{
printf("0x%p CTEST is destructed\n", this);
}
}; CTEST GetCTest()
{
CTEST oCtest; return oCtest;
} int main(int argc, char* argv[])
{
printf("***************************Test1***************************\n\n");
CTEST oTest1 = GetCTest();
printf("oTest1 address is 0x%p\n", &oTest1);
printf("\n"); printf("***************************Test2***************************\n\n");
CTEST oTest2;
printf("oTest2 address is 0x%p\n", &oTest2);
oTest2 = GetCTest();
printf("\n"); printf("***************************Test3***************************\n\n");
GetCTest();
printf("\n"); getchar();
return 0;
}

运行结果

1.2
CTEST oTest1 = GetCTest();
        用返回对象定义赋值对象时,oTest1的构造函数并不会被调用,而是传递其对象的指针作为隐含参数给GetCTest()函数,

GetCTest()会在函数对象返回时调用其拷贝构造函数,利用返回对象对其初始化。

1.3 oTest2 = GetCTest();
        用返回对象赋值对象时,与定义赋值不同,并不会传递其对象的指针给GetCTest()函数,而是产生了一个临时对象作为隐含参

数传递给GetCTest()函数,GetCTest()函数执行完毕后,利用临时对象给oTest2对象赋值(即浅拷贝,而不是调用其拷贝构造函数,如

果有资源指针,可能会造成资源泄露,有兴趣的朋友可以深入研究下这个问题)。

1.4 GetCTest();
        单独调用GetCTest()函数和1.3类似,也会产生临时对象,只是调用结束后会析构掉。

二、深入分析
2.1 GetCTest()反汇编分析

7:    CTEST   GetCTest()
8: {
9: CTEST oCtest;
00401074 lea ecx,[ebp-10h]
00401077 call @ILT+5(CTEST::CTEST) (0040100a)
0040107C mov dword ptr [ebp-4],1
10:
11: return oCtest;
00401083 lea eax,[ebp-10h]
00401086 push eax //压入oCtest对象指针
00401087 mov ecx,dword ptr [ebp+8] //取赋值对象的指针,该指针在调用GetCTest()函数时隐式传入
0040108A call @ILT+20(CTEST::CTEST) (00401019) //调用赋值对象的拷贝构造函数
0040108F mov ecx,dword ptr [ebp-14h]
00401092 or ecx,1
00401095 mov dword ptr [ebp-14h],ecx
00401098 mov byte ptr [ebp-4],0
0040109C lea ecx,[ebp-10h]
0040109F call @ILT+15(CTEST::~CTEST) (00401014) //返回对象oCtest析构
004010A4 mov eax,dword ptr [ebp+8] //返回赋值对象的指针
12: }

通过以上反汇编代码的分析,可以看出GetCTest()函数在调用时编译器偷偷摸摸的传入了赋值对象的指针,而返回对象的函数

实际上在返回时已经将返回对象析构了,其返回的是赋值对象的指针,只是在析构前利用返回对象其赋值对象进行拷贝构造了。

2.2 代码反汇编分析

17:       CTEST oTest1 = GetCTest();
0040123A lea eax,[ebp-10h]
0040123D push eax //压入oTest1的指针,以供GetCTest拷贝构造对象
0040123E call @ILT+0(GetCTest) (00401005)
00401243 add esp,4
00401246 mov dword ptr [ebp-4],0
18: printf("oTest1 address is 0x%p\n", &oTest1);
0040124D lea ecx,[ebp-10h]
00401250 push ecx
00401251 push offset string "oTest1 address is 0x%p\n" (00427164)
00401256 call printf (004018a0)
0040125B add esp,8 20:
21: printf("***************************Test2***************************\n\n");
0040126B push offset string "***************************Test2"... (00427114)
00401270 call printf (004018a0)
00401275 add esp,4
22: CTEST oTest2;
00401278 lea ecx,[ebp-14h] //调用oTest2的构造函数
0040127B call @ILT+5(CTEST::CTEST) (0040100a)
00401280 mov byte ptr [ebp-4],1
23: printf("oTest2 address is 0x%p\n", &oTest2);
00401284 lea edx,[ebp-14h]
00401287 push edx
00401288 push offset string "oTest2 address is 0x%p\n" (004270f8)
0040128D call printf (004018a0)
00401292 add esp,8
24: oTest2 = GetCTest();
00401295 lea eax,[ebp-1Ch] //压入临时对象的指针
00401298 push eax
00401299 call @ILT+0(GetCTest) (00401005)
0040129E add esp,4
004012A1 mov dword ptr [ebp-28h],eax //保存GetCTest返回的对象地址到[ebp-28h]
004012A4 mov ecx,dword ptr [ebp-28h]
004012A7 mov edx,dword ptr [ecx] //拷贝GetCTest返回的对象的m_nData参数至oTest2对象的m_nData
004012A9 mov dword ptr [ebp-14h],edx
004012AC lea ecx,[ebp-1Ch] //临时对象析构
004012AF call @ILT+15(CTEST::~CTEST) (00401014) 26:
27: printf("***************************Test3***************************\n\n");
004012C1 push offset string "***************************Test3"... (004270ac)
004012C6 call printf (004018a0)
004012CB add esp,4
28: GetCTest();
004012CE lea eax,[ebp-20h] //压入临时对象的指针
004012D1 push eax
004012D2 call @ILT+0(GetCTest) (00401005)
004012D7 add esp,4
004012DA lea ecx,[ebp-20h] //临时对象析构
004012DD call @ILT+15(CTEST::~CTEST) (00401014)

C++浅析——返回对象的函数的更多相关文章

  1. js创建对象的三种方法:文本标识法和构造器函数法和返回对象的函数

    文本标识法和定义变量差不多,像这样 var obj = {name:'HanMM','2':'Dali'}; 函数构造器法  先创建一个对象函数 function Obj() { this.addre ...

  2. javascript 对象初探(二)--- 返回对象的函数

    除了使用new操作符调用构造函数以外,我们也可以抛开new操作符,只用一般函数来创建对象,这样就能执行某些预备工作,并已对象为返回值的函数.. function her(){ return { nam ...

  3. JavaScript (JS) 面向对象编程 浅析 (含对象、函数原型链、闭包解析)

    1. 构造函数原型对象:prototype ① 构造函数独立创建对象,消耗性能 function Person(name) { this.name = name; this.sayHello = fu ...

  4. c++怎样让返回对象的函数不调用拷贝构造函数

    我们知道拷贝构造函数有两种“默默”的方式被调用 1. 想函数传入 值参数 2. 函数返回 值类型 今天我们讨论函数返回值类型的情况. 得到结论是 1. 当对象有拷贝构造函数(系统为我们生成.或者我们自 ...

  5. 孤荷凌寒自学python第十九天python函数嵌套与将函数作为返回对象及闭包与递归

    孤荷凌寒自学python第十九天python函数嵌套与将函数作为返回对象及闭包与递归 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) Python函数非常的灵活,今天学习了python函数的以 ...

  6. c++逆向分析----返回对象

    对象不使用默认析构函数 class Test { public: char cNum1; int iNum2; int* pInt; }; Test _ReturnObject() { Test st ...

  7. 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针

      您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. ...

  8. STL算法设计理念 - 函数对象和函数对象当参数和返回值

    函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特征,就是通过"对象名+(参数列表)&qu ...

  9. oracle 用函数返回对象集合

    1.先要声明全局type:并且,字段变量类型要为object,不能为record: (1)CREATE OR REPLACE TYPE "DDD_BY_DEPT_STATISTISC&quo ...

随机推荐

  1. ios svn无法连接xp或者win7系统svn的解决方法

    找到服务器svn的安装目录,或者直接查找httpd.conf,找到端口号,复制到ios系统的svn端口号,就ok了,如图 这是其他人的解决方法 Subversion有两种不同的配置方式,一种基于它自带 ...

  2. jQuery cxSlide 焦点图轮换

    cxSlide 是一个简单易用的焦点图展示插件,支持水平.纵向切换,透明过渡切换. 已支持 CSS 动画过渡切换.通过 CSS 动画切换,可以展示更多效果. 版本: jQuery v1.7+ jQue ...

  3. 关于HTML面试题汇总之visibility

    一.页面可见性(visibility) 主要提供两个属性,一个事件(都在document对象上):1. 属性:   1.1.  hidden:获取或设置当前页面的可见性,boolean值:   1.2 ...

  4. Framework7 – 赞!功能齐全的 iOS7 App 前端框架

    Framework7 是一个功能很全的 HTML 框架,用来构建 iOS7 应用程序. Framework7 允许您灵活搭建列表视图(表视图) .你可以让他们作为导航菜单,你可以在列表里面使用图标,输 ...

  5. jQuery立体式数字滚动条增加

    1.html结构 <div class="numberRun1"></div> 2.js <script type="text/javasc ...

  6. CSS3简单动画

    css3的动画确实非常绚丽!浏览器兼容性很重要!. 分享两个小动画 <!doctype html> <html lang="en"> <head> ...

  7. div水平居中

    1.先给它外层的div定位并left:position:absolute;left:50%; 2.获取当前元素div的宽度,并除以2 3.改变它的css:margin-left:-(获取当前元素div ...

  8. css3中filter的各种特效

    css3中的filter属性可以说是简单易用且强大,这些效果作用在图片上实现一些特效(也可以作用在vidio上,此处只讨论图片特效). 浏览器兼容性 目前各大浏览器对于css3的兼容已经非常好了,最新 ...

  9. 【转】扫盲 同步利器、分布式网盘--BT Sync

    原文地址:http://program-think.blogspot.com/2015/01/BitTorrent-Sync.html先向大伙儿宣布个好消息——经过多位热心读者的大力支持,经过几天的努 ...

  10. JNI输出log信息

    1.修改Android.mk 如生成的库文件是“.so文件”,则在Android.mk中添加如下内容: LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog 如生成的库文件 ...