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 ...
随机推荐
- hg vs git :这个世界除了svn还有别的
最近想用版本控制软件来保存汉化文件,但又觉得SVN太麻烦,于是想到了最近较为流行的分布式版本控制工具.而Git和Mercurial(意思为水银的,于是经常缩写为Hg)自然是其中最为流行的工具.大名鼎鼎 ...
- error proc
/*************************************************************************\ * Copyright (C) Michael ...
- [BZOJ 3894] 文理分科 【最小割】
题目链接:BZOJ - 3894 题目分析 最小割模型,设定一个点与 S 相连表示选文,与 T 相连表示选理. 那么首先要加上所有可能获得的权值,然后减去最小割,即不能获得的权值. 那么对于每个点,从 ...
- RedHat 6.5 离线安装 apache2.4.23
第一部分:安装gcc等 rpm -ivh mpfr-2.4.1-6.el6.x86_64.rpm rpm -ivh ppl-0.10.2-11.el6.x86_64.rpm rpm -ivh cpp- ...
- Javascript函数中传递带空格的参数
通常在页面中要让某些内容点击后产 生点击事件(非页面跳转)都会使用onclick,但是这样不适于需要传递参数的情况,于是写成直接调用Javascript函数的方式:<a href=javascr ...
- Condition 的使用
Condition 将 Object 监视器方法(wait.notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set ...
- pl/sql 关于变量定义的问题
1. create or replace procedure test_prc(p_data_dt in date) IS e_name emp.ename%type; begin sel ...
- Android MonkeyRunner自动拨打电话
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice import time device = MonkeyRunner.wa ...
- Dynamic系列--Dynamic 与反序列化
通常在调用其他站点的api时,如果返回的结果为 json数据,而我们又不想再重新定义实体类时,可以使用dynamic类型. 但是有以下需要注意的地方. 当内容为空时,反序列化结果为null 当内容格式 ...
- BZOJ3036: 绿豆蛙的归宿&Wikioi2488:绿豆蛙的归宿
3036: 绿豆蛙的归宿 Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 108 Solved: 73[Submit][Status] Descript ...