加载中…
正文 字体大小:

函数返回引用类型和非引用类型的区别

(2011-03-12 11:29:15)
分类: CppSTL

函数返回引用类型 和 非引用类型究竟有什么不同呢?

先来个总结:非引用类型返回值的函数,返回的是一个新的临时对象。

 

分析见下图:

#include <iostream>
using namespace std;
class CText
{
public:
 ~CText()
 {
  cout<<"析构了"<<this<<endl;
 }
};

CText& fRefer(CText &a)
{
 return a;
}

CText fNoRefer(CText &a)
{
 return a;
}


int main(int arge,char*argv[ ])
{
 CText a;
 cout<<"a的地址:"<<&a<<endl;

 cout<<endl<<"------引用类型返回值------"<<endl;
    a=fRefer(a);

 cout<<endl<<"------非引用类型的返回值------"<<endl;
    a=fNoRefer(a);

 cout<<endl<<"------main结束------"<<endl;
 return 0;
}

 

运行结果:

函数返回引用类型和非引用类型的区别 图1
如图,在调用非引用类型返回值函数的时候会多出了一个临时的对象。

多出的临时对象究竟有什么用呢?

 

我们用反汇编再深入看看内部运行过程。

如果对反汇编调试不太熟的朋友,请先看:《反汇编学习》

在看引用类型返回值函数之前先看看返回引用类型值的函数调用过程,如图:

函数返回引用类型和非引用类型的区别图2

解读:[ebp-10h]存放的是a对象的地址,把a作为参数压栈,然后调用fRefer。

fRefer内部:(只看红色部分)

函数返回引用类型和非引用类型的区别     图3
解读:[ebp+8]就是fRefer的参数a,直接将a返回。

接下来就看非引用类型返回值函数如图:

函数返回引用类型和非引用类型的区别图4

解读:将a对象的地址作为参数压入栈,然后调用fNoRefer。咦? 怎么压2个参数到栈里?一个是a对象的地址,另一个是?

这里,细心的读者可以发现另外一个参数正是图1里冒出来的临时对象。

fNoRefer函数的内部:(重点看红色框内部)

 函数返回引用类型和非引用类型的区别图5

解读:[ebp+0Ch]是第一个参数即a对象的地址,[ebp+8]是第二个参数即临时产生的对象。将a赋值给临时对象,然后将临时对象返回。
回到图4,最后将返回值(即临时对象)赋值给a,然后销毁临时对象。

函数返回引用类型和非引用类型的区别

结论:非引用类型返回的是临时对象。

可见非引用类型的不但要多建一个临时对象,还会多出了不少的语句从而多消耗CPU性能。

 

如果还觉得晕晕的,我再举个例子:

#include <iostream>
using namespace std;
class CText
{
public:
 void say()
 {
  cout<<"我是"<<this<<endl;
 }
 ~CText()
 {
  cout<<"析构了"<<this<<endl;
 }
};

CText& fRefer(CText& a)
{
 return a;
}

CText fNoRefer(CText& a)
{
 return a;
}

int main(int arge,char*argv[ ])
{
 CText a;
 cout<<"a的地址:"<<&a<<endl;

 cout<<endl<<"------引用类型返回值------"<<endl;
    fRefer(a).say();
 cout<<endl<<"------非引用类型的返回值------"<<endl;
    fNoRefer(a).say();
 cout<<endl<<"------main结束------"<<endl;
 return 0;
}

结果:

函数返回引用类型和非引用类型的区别

0

阅读 评论 收藏 转载 喜欢 打印举报
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有