c++中返回对象与返回引用的区别
这几天在做用C++做课程设计,对其返回对象的实现感到迷惑。
通过对汇编代码的分析,可以清楚的看到,直接返回引用和返回对象的区别到底是什么。
分析的程序如下
#include<cstdio>
class Node
{
public:
Node(int _num, char *_str):
num(_num), str(_str)
{
}
int getInt()
{
return num;
};
void setInt(int n)
{
num = n;
}
char* getStr()
{
return str;
}
private:
int num;
char *str;
};
Node node(,"good");
Node getNode1()
{
return node;
}
Node& getNode2()
{
return node;
}
int main()
{
Node node1 = getNode1();
printf("%d,%s",node1.getInt(),node1.getStr());
Node node2 = getNode2();
printf("%d,%s",node2.getInt(),node2.getStr());
;
}
有两个getNode函数,一个直接返回对象,一个返回对象的引用。
反汇编结果(采用MinGW编译器)
. ; Node getNode1() . public __Z8getNode1v . __Z8getNode1v proc near ; CODE XREF: _main+Fp . push ebp . mov ebp, esp . mov eax, ds:_node.num ;将成员num的值放到eax寄存器 . mov edx, ds:_node.str ;将成员str的值放到eda寄存器 .text:0040157E pop ebp .text:0040157F retn .text:0040157F __Z8getNode1v endp .text:0040157F . . ; =============== S U B R O U T I N E ======================================= . . ; Attributes: bp-based frame . . ; Node *getNode2() . public __Z8getNode2v . __Z8getNode2v proc near ; CODE XREF: _main+48p . push ebp . mov ebp, esp . mov eax, offset _node ;将node对象的地址值放到eax寄存器 . pop ebp . retn . __Z8getNode2v endp . .text:0040158A .text:0040158A ; =============== S U B R O U T I N E ======================================= .text:0040158A .text:0040158A ; Attributes: bp-based frame .text:0040158A .text:0040158A ; int main() .text:0040158A public _main .text:0040158A _main proc near ; CODE XREF: ___tmainCRTStartup+25Dp .text:0040158A . .text:0040158A .text:0040158A push ebp .text:0040158B mov ebp, esp .text:0040158D push ebx .text:0040158E and esp, 0FFFFFFF0h . sub esp, 20h ;开辟栈空间 . call ___main . call __Z8getNode1v ; getNode1(void) .text:0040159E mov [esp+18h], eax ;取出成员num的值放到栈中 .text:004015A2 mov [esp+1Ch], edx ;去除成员str的值放到栈中 .text:004015A6 lea eax, [esp+18h] ;栈中对象的首地址存取eax寄存器,当作.text:004015AC处函数调用的参数 .text:004015AA mov ecx, eax .text:004015AC call __ZN4Node6getStrEv ; Node::getStr(void) .text:004015B1 mov ebx, eax .text:004015B3 lea eax, [esp+18h] ;栈中对象的首地址存取eax寄存器,当作.text:004015B9处函数调用的参数 .text:004015B7 mov ecx, eax .text:004015B9 call __ZN4Node6getIntEv ; Node::getInt(void) .], ebx .], eax .text:004015C6 mov dword ptr [esp], offset __format ; this .text:004015CD call __Z6printfPKcz ; printf(char const*,...) .text:004015D2 call __Z8getNode2v ; getNode2(void) .] ;返回值为Node对象的首地址,存放在eax寄存器中,此处取其成员str的值 .text:004015DA mov eax, [eax] ;返回值为Node对象的首地址,存放在eax寄存器中,此处取其成员num的值 .text:004015DC mov [esp+10h], eax ;将Node对象首地址放到栈中(esp+10h处) .text:004015E0 mov [esp+14h], edx .text:004015E4 lea eax, [esp+10h] ;将栈中esp+10h处存放的Node对象首地址放到eax中,为函数调用的参数 .text:004015E8 mov ecx, eax .text:004015EA call __ZN4Node6getStrEv ; Node::getStr(void) .text:004015EF mov ebx, eax ;返回的字符串首地址存在eax寄存器中,此处复制到ebx寄存器中 .text:004015F1 lea eax, [esp+10h] ;将栈中esp+10h处存放的Node对象首地址放到eax中,为函数调用的参数 .text:004015F5 mov ecx, eax .text:004015F7 call __ZN4Node6getIntEv ; Node::getInt(void) .], ebx . ], eax . mov dword ptr [esp], offset __format ; __format .text:0040160B call __Z6printfPKcz ; printf(char const*,...) 此函数参数用栈传递 esp+8为字符串首地址 esp+4为num . . mov ebx, [ebp+var_4] . leave . retn . _main endp
在汇编代码中,可以清楚的看到函数返回引用实际是返回的一个指针,直接返回对象则会把对象中的数据全部复制(此处只有一个int和一个char指针,所以用了两个寄存器,如果数据项很多则会使用栈传递)。
Node node2 = getNode2(); //此函数返回对象引用
而对于上边这句,由于node2为一个存在栈中的对象,所以会根据getNode1函数返回的指针将其指向对象所有的数据全部拷贝到栈中对象的空间内。
对于
Node node1 = getNode1();//此函数直接返回对象
是将此函数的返回数据全部拷贝到栈中,返回的数据包含原对象的所有数据。
综上
c++中返回对象引用实际是返回的对象指针,直接返回对象会把对象的数据全部拷贝一遍(拷贝到寄存器或栈中)。
而对于将返回值赋值给一个对象时,如果函数返回的是引用,则会根据指针将所有数据拷贝过去,如果返回的是对象,会把返回的对象的数据(可能在寄存器中,或栈中)再拷贝到需赋值的对象中去。
所以
Node node = getNode()
如果函数返回对象引用,对象的数据会被拷贝一次,如果直接返回对象,则会被拷贝两次。
c++中返回对象与返回引用的区别的更多相关文章
- C++返回对象和返回引用
我们发现,在C++中,有些成员函数返回的是对象,而有些函数返回的又是引用. 返回对象和返回引用的最主要的区别就是函数原型和函数头. Car run(const Car &) //返回对 ...
- [转]ThinkPHP中实例化对象M()和D()的区别,select和find的区别
1.ThinkPHP中实例化对象M()和D()的区别 在实例化的过程中,经常使用D方法和M方法,这两个方法的区别在于M方法实例化模型无需用户为每个数据表定义模型类,如果D方法没有找到定义的模型类,则会 ...
- ThinkPHP中实例化对象M()和D()的区别,select和find的区别
原文:ThinkPHP中实例化对象M()和D()的区别,select和find的区别 1.ThinkPHP中实例化对象M()和D()的区别 在实例化的过程中,经常使用D方法和M方法,这两个方法的区别在 ...
- ThinkPHP中实例化对象M()和D()的区别
ThinkPHP中实例化对象M()和D()的区别 ThinkPHP中实例化对象M()和D()的区别?ThinkPHP如何实例化对象?在实例化的过程中,经常使用D方法和M方法,这两个方法的区别在于M方法 ...
- C#中Monitor对象与Lock关键字的区别分析
这篇文章主要介绍了C#中Monitor对象与Lock关键字的区别,需要的朋友可以参考下 Monitor对象 1.Monitor.Enter(object)方法是获取 锁,Monitor.Exit(ob ...
- (C/C++学习)21.C++中返回引用和返回对象以及传引用和传对象问题
说明:在学习和编写C++代码时,经常会遇到这样的问题:一个带返回值的函数,到底应该返回值呢,还是应该返回引用呢:在传递参数的时候,是应该传递参数的引用呢,还是应该传值呢?请看下面代码: void my ...
- [转] C++中临时对象及返回值优化
http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...
- 转:C++中临时对象及返回值优化
http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...
- Vue中data返回对象和返回值的区别
速记:粗浅的理解是,事件的结果是影响单个组件还是多个组件.因为大部分组件是要共享的,但他们的data是私有的,所以每个组件都要return一个新的data对象 返回对象的时候 <!DOCTYPE ...
随机推荐
- ios开发之C语言第一天
最近在学习ios开发,先学习C语言,再学习OC和swift.正所谓"万丈高楼平地起",打好基础是很重要的,所以C语言也必须好好学习.学习中所使用的操作系统是OS X,开发工具是Xc ...
- 应用git(SSH设置)
git配置完成email和user后,才可以生成SSH Key. $ git config --global user.name "自定义名称" $ git config --gl ...
- VLD(Visual LeakDetector)内存泄露库的使用
VLD简介 由于C/C++语言没有所谓的垃圾收集器,内存的分配和释放都需要程序员自己来控制,这会给C/C++程序员带来一定的困难.当您的程序越来越复杂时,它的内存管理也会变得越来越困难.内存泄漏.内存 ...
- This configuration file was broken by system-config-keyboard
posts • Page of problem with startx Postby evarie » // :: Normally i can get started with the x wind ...
- Invitation Cards(邻接表+逆向建图+SPFA)
Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 17538 Accepted: 5721 Description In ...
- VM Depot 镜像新增系列II – 学习管理系统,内容管理系统以及平台管理工具
发布于 2014-06-23 作者 刘 天栋 继上周企业管理软件和电子商务镜像的加盟之后,我们看到又有一批内容管理解决方案(CMS),学习管理解决方案(LMS)以及平台管理工具 (如 Open ...
- [转载]函数getopt(),及其参数optind
最近用到了getopt()这个函数,对它进行了一些了解.这篇博文还是写的非常清楚的.值得学习.最近在改进一个开源项目,希望自己能静下心好好分析代码. ------------------------- ...
- ANDROID Porting系列一、ANDROID编译系统
译自:http://source.android.com/porting/build_system.html Android使用一个自定义生成系统生成工具,二进制文件和文档.本文档提供了一个建立And ...
- awk替换第几行第几列的值
代码如下: awk '{if(2==NR){gsub(/.*/, 300, $5)}print}' list.txt 将文件list.txt的第2行第5列的值替换为300
- 【转】SVN linux命令及 windows相关操作(一)
从以下博客转载和整理: http://www.cnblogs.com/richcem/archive/2011/01/08/1930823.html http://blog.wpjam.com/m/t ...