return临时变量的问题

1. return临时变量问题

#include<iostrea>
int a,i;
int fun()
{
int b=1,c=2;
a=b+c;
return a;
}
i=fun()

想问下,是a赋值给i,还是a的临时副本赋值给i?我试过了,会产生临时副本的。兄弟们,我的意思是问,既然a是全局变量了,又不会消失,怎么还会产生临时副本。如果a是局部变量 ,还好理解,因为a出了函数的作用域就会消失,所以系统会产生临时副本来代替a赋值等等的回答。

我来回答你的问题:

首先,这里必须是传递a的副本

其次,为什么传递副本,不是由a的生命周期来定义的,比如a是否是全局,或者局部,甚至是static,都与是否传递副本没有关系的

最后,这里传递副本是取决于fun函数的,fun函数返回的类型是 int,也就是说返回值的传递时采用”值传递”,你应该懂这个名词,不是地址传递,而值传递,明显特征是要传递副本;

换句话说,如果定义fun函数如下:

int& fun();

那么可以return a,不会有副本产生。注意必须是a为全局的情况下,否则会引起警告,禁止传递局部变量的引用,因为a的声明周期会马上结束掉。

到此,已经解答了楼主的问题。我想多说一句:为什么不写成int& fun();这种形式呢?答案是没必要。int是内部自定义类型。对于自定义变量而言,引用与否引起的副本拷贝带来的工作量不是很大,相反,如果是自定义类型,不知道楼主学习了class没有,那么引用返回就非常有必要了。因为带来的副本拷贝可能非常耗时,而这也是C++之父strup反复强调了,也是我们需要常常使用的。

2. return变量/对象,采用pass-by-value会产生临时变量,调用拷贝构造和析构

返回值优化(RVO)(无名返回值)

MyCla TestFun() {
    return MyCla();
}
具体现象分析

考虑到汇编层面!

在没有任何“优化”之前,这段代码的行为也许是这样的:return MyCla() 这行代码中,构造了一个 MyCla 类的临时的无名对象(姑且叫它t1),接着把 t1 拷贝到另一块临时对象 t2(不在栈上),然后函数保存好 t2 的地址(放在 eax 寄存器中)后返回,TestFun 的栈区间被“撤消”(这时 t1 也就“没有”了,t1 的生存域在 TestFun 中,所以被析构了),在 MyCla a = TestFun(); 这一句中,a 利用 t2 的地址,可以找到 t2,接着进行构造。这样 a 的构造过程就完成了。然后再把 t2 也“干掉”。

优化方案

在这个过程中,t1 和 t2 这两个临时的对象的存在实在是很浪费的,占用空间不说,关键是他们都只是为a的构造而存在,a构造完了之后生命也就终结了。既然这两个临时的对象对于程序员来说根本就“看不到、摸不着”(匿名对象嘛,你怎么引用?),于是编译器干脆在里面做点手脚,不生成它们!怎么做呢?很简单,编译器“偷偷地”在我们写的fun函数中增加一个参数 A&,然后把 a 的地址传进去(注意,这个时候 a 的内存空间已经存在了,但对象还没有被“构造”,也就是构造函数还没有被调用),然后在函数体内部,直接用 a 来代替原来的“匿名对象”,在函数体内部就完成 a 的构造。这样,就省下了两个临时变量的开销。这就是所谓的“返回值优化”~!在 VC7 里,按值返回匿名对象时,默认都是这么做。

具命返回值优化(NRVO)

MyCla TestFun2() {
    MyCla x(3);
    return x;
}

对于按值返回“具名对象”(就是有名字的变量!)时的优化手段,其实道理是一样的,但由于返回的值是具名变量,情况会复杂很多。

对于 C++ 编译器来说,只要你写的程序是把对象按值返回的,它会有两种做法,来避免 t2 的产生。

优化方案一

一种做法是像 RVO一样,把作为表达式中获取返回值来进行构造的变量 a 当成一个引用参数传入函数中,然后在返回语句之前,用要返回的那个变量来拷贝构造 a,然后再把这个变量析构,函数返回原调用点,a 就构造好了。

优化方案二

还有一种方式,是在函数返回的时候,不析构 x ,而直接把 x 的地址放到 exa 寄存器中,返回调到 TestFun2 的调用点上,这时,a 可以用 exa 中存着的地址来进行构造,a 构造完成之后,再析构原来的变量 x !是的,注意到其实这时,x 的生存域已经超出了 TestFun2,但由于这里 x 所在 TestFun2 的栈虽然已经无效,但是并没有谁去擦写这块存,所以 x 其实还是有效的,当然,一切都在汇编的层面,对于 C++ 语言层面来讲是透明的。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值