一、原码分析
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. 从基础学起----xuld版高手成长手记[1]

    别人的代码总是看不懂? 想实现一个功能总是无从下手? 学会一个,但稍微变个花样就不知道了? 无论你擅长什么编程语言,如果你觉得自己基础薄弱,想从头开始学起,那本文将适合你. 这篇文章的含金量非常高,如 ...

  2. 开发 web 桌面类程序几个必须关注的细节

    HoorayOS 写了差不多快2年了,在我的坚持下也有一部分人打算着手自己也写套类似的程序,我想我可以提供一点经验. 俗话说细节决定成败,开发2年多来,我看过大大小小类似的程序不下20个,各有优点也各 ...

  3. Quartz.NET开源作业调度框架系列(五):AdoJobStore保存job到数据库

    Quartz.NET 任务调度的核心元素是 scheduler, trigger 和 job,其中 trigger(用于定义调度时间的元素,即按照什么时间规则去执行任务) 和 job 是任务调度的元数 ...

  4. SlidesJS - 老牌的响应式 jQuery 幻灯片插件

    SlidesJS 是一款老牌的 jQuery 幻灯片插件,经过多年的发展,已经成为一款功能齐全,设计精巧的幻灯片插件.支持循环.自动播放功能和淡入淡出过渡效果,并且能够自动生成分页,可以帮助开发者制作 ...

  5. go语言 类型:基础类型和复合类型

    Go 语言中包括以下内置基础类型:布尔型:bool整型:int int64 int32 int16 int8 uint8(byte) uint16 uint32 uint64 uint浮点型:floa ...

  6. php代码美化/格式化 还原 -问题

    使用某个PHP代码格式化的工具.源代码: if ($this->_standardize_newlines == TRUE) { if (strpos($str, "\r") ...

  7. 最近学习了Node,利用Express搭建了个人博客,总结下吧

    node+express+jade+mongodb搭建了一套个人博客,我来总结下这几个家伙的使用感受吧! [node] 成熟插件库众多,真的是只有你想不到,没有它做不到的.而且对于有前端JS基础的童鞋 ...

  8. Swift安装

    Server1 .Update sudo apt-get update sudo apt-get upgrade . sudo apt-get install bridge-utils .IP 3.1 ...

  9. 设置UIImage的渲染模式:UIImage.renderingMode

    设置UIImage的渲染模式:UIImage.renderingMode 着色(Tint Color)是iOS7界面中的一个.设置UIImage的渲染模式:UIImage.renderingMode重 ...

  10. iOS 开发之路(登陆页键盘遮挡输入框问题)一

    在学习开发登陆页的时候,遇到的问题分享如下: 首先是swift 3.0 中,NotificationCenter 设置 selector 如下: @IBOutlet weak var bottomCo ...