C++愤恨者札记2——函数返回值为类对象
来源:互联网 发布:支持一夫多妻知乎 编辑:程序博客网 时间:2024/05/17 21:59
C++愤恨者札记2——函数返回值为类对象
为避免冗余代码,程序使用Release配置编译,但要把/Od选项打上,否则编译器优化,会使用代码很难懂。当函数返回值是基本的数据类型(如,int,char)时,会把返回结果放在eax上,这样函数调用者就可以通过eax获得函数返回结果了。但如果返回值是一个类对象呢?eax根本不够用了。
实验源码:
class Node{public: Node(){} //Node(Node& n){} int data1; int data2; int data3;};Node Fn(){ Node n; n.data1 = 100; return n;}void main(){ Fn();}
----------------------------------------------------------------------
调用者处理过程。main将会在栈上为Fn分配临时空间,大小为其返回对象尺寸,代码没有优化的前提下,Fn出现一次会分配一份,出现两次则两份,依此类推。可以把"Fn ();"复制几次试试。调用Fn时,为Fn分配的临时空间的地址将压栈,Fn内部将使用这个地址来存放返回结果。
hello!main:012a1040 55 push ebp012a1041 8bec mov ebp,esp012a1043 83ec0c sub esp,0Ch;开辟临时空间,sizeof(Node)大小就是12,即0CH012a1046 8d45f4 lea eax,[ebp-0Ch]012a1049 50 push eax;压入临时空间地址012a104a e8c1ffffff call hello!Fn (012a1010)012a104f 83c404 add esp,4012a1052 33c0 xor eax,eax012a1054 8be5 mov esp,ebp012a1056 5d pop ebp
----------------------------------------------------------------------
无拷贝构造函数的情况下,Fn的反汇编结果。Fn会把结果拷贝到临时空间中去,而这个临时空间的地址在main调用Fn时,已经压入栈了。
hello!Fn [e:\hello\hello\hello.cpp @ 29]:29 012a1010 55 push ebp29 012a1011 8bec mov ebp,esp29 012a1013 83ec0c sub esp,0Ch;分配内存30 012a1016 8d4df4 lea ecx,[ebp-0Ch];无参构造函数的this指针30 012a1019 e8e2ffffff call hello!Node::Node (012a1000);无参构造函数调用31 012a101e c745f464000000 mov dword ptr [ebp-0Ch],64h;n.data1 = 100;33 012a1025 8b4508 mov eax,dword ptr [ebp+8];调用Fn时压入的临时空间地址33 012a1028 8b4df4 mov ecx,dword ptr [ebp-0Ch];复制第一个成员data133 012a102b 8908 mov dword ptr [eax],ecx33 012a102d 8b55f8 mov edx,dword ptr [ebp-8];复制第二个成员data233 012a1030 895004 mov dword ptr [eax+4],edx33 012a1033 8b4dfc mov ecx,dword ptr [ebp-4];复制data3,如果成员很多33 012a1036 894808 mov dword ptr [eax+8],ecx;则会使用rep movs来复制33 012a1039 8b4508 mov eax,dword ptr [ebp+8]34 012a103c 8be5 mov esp,ebp34 012a103e 5d pop ebp34 012a103f c3 ret
----------------------------------------------------------------------
加上拷贝构造函数后(去掉注释后),Fn把复制工作交给拷贝构造函数去做,临时空间地址也交给它。所以被调用的拷贝构造函数将影响到main中分配的临时空间,从而实现了数据的传递,即类对象的返回。
hello!Fn:01381020 55 push ebp01381021 8bec mov ebp,esp01381023 83ec0c sub esp,0Ch;分配内存01381026 8d4df4 lea ecx,[ebp-0Ch]01381029 e8d2ffffff call hello!Node::Node (01381000);构造函数0138102e c745f464000000 mov dword ptr [ebp-0Ch],64h;n.data1 = 100;01381035 8d45f4 lea eax,[ebp-0Ch]01381038 50 push eax01381039 8b4d08 mov ecx,dword ptr [ebp+8];临时空间地址,作为this指针0138103c e8cfffffff call hello!Node::Node (01381010);调用拷贝构造函数01381041 8b4508 mov eax,dword ptr [ebp+8]01381044 8be5 mov esp,ebp01381046 5d pop ebp01381047 c3 ret
- C++愤恨者札记2——函数返回值为类对象
- C++愤恨者札记1——类对象作为函数参数的数据传递过程
- C++愤恨者札记6——函数指针与函数对象
- C++愤恨者札记3——函数调用约定
- C++愤恨者札记7——函数适配器
- C++愤恨者札记1——类对象作为函数参数的数据传递过程 http://blog.csdn.net/tms_li/article/details/7765626
- C++愤恨者札记4——拷贝构造函数被调用的四种情形
- C++愤恨者札记10——bind2nd示例
- C++愤恨者札记5——临时变量的内存分配
- C++愤恨者札记8—— 常引用参数也不可靠的情况
- C++愤恨者札记9——vector.erase与set.erase
- 返回值为对象的函数识别
- 返回值为对象的函数
- C/CPP中main函数返回值为1——找工作学到的
- 返回值为C/C++函数指针的函数
- C语言函数返回值为指针和函数返回值为void
- 返回值为对象调用拷贝构造函数
- C:返回值为指针的函数解读
- 常用记账软件总结
- SOJ 2745 树状数组 TOJ 3505 树状数组
- 找出字符串中对称的子字符串的最大长度(最长回文)
- poj1062
- Django 和时区设置的问题
- C++愤恨者札记2——函数返回值为类对象
- HDU 1712 ACboy needs your help
- vim 中定义快捷键的方法
- Spring怎样配置JNDI数据源
- 记录今天因oracle监听不能启动,报错误问题
- 解析C++中ifstream 与ofstream的用法
- PHP面向对象学习备份源代码(1)
- SCU 10届 没有女队
- EXCEL 2013 - POWER VIEW 之一