函数返回值与临时变量的问题

mutable 2007-12-04 10:48:58

class X
{
int i;
public:
X(int ii=0);
X(X &a);
~X();
void modify();
};


X::X(int ii)
{
i=ii;
cout<<"constructor "<<this->i<<endl;
}


X::X(X &a)
{
i=a.i;
cout<<"copy "<<this->i<<endl;
}


X::~X()
{
cout<<"destructor "<<this->i<<endl;
}


void X::modify()
{
i++;
}


X f5()
{
return X();
}


void main()
{
X a(10);
f5()=a;

}


/////////////////////////////
结果是:
constructor 10 //对象a构造函数
constructor 0 //f5()函数中X()构造函数
destructor 10 //析构
destructor 10 //析构

编译器不是要产生一个临时对象来保存f5()返回值吗??
可是从结果上看并没有调用构造函数或拷贝构造函数来产生一个临时变量来接受对象a的赋值啊????
...全文
557 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuntongsf 2010-09-29
  • 打赏
  • 举报
回复
将f5()里X()改为X p;return p;就可以得到你想要的结果
xiaoxin_ye 2008-03-25
  • 打赏
  • 举报
回复
f5()=a;
上面这句话还是没有理解
从蓝田到元谋 2007-12-05
  • 打赏
  • 举报
回复
那么将该函数写成返回一个引用,函数里面创建的对象在该函数结束时就撤销了,也就是纯粹的临时变量?
这之间区别在哪?编译器怎么对待两者?
yuyunliuhen 2007-12-04
  • 打赏
  • 举报
回复
learning...
mutable 2007-12-04
  • 打赏
  • 举报
回复
楼上说的我都明白。

关键是对于表达式f5()=a,是把a的内容直接赋值给函数f5()的返回值那块内存,还是函数f5()从已经生成的返回值再产生一个临时变量去接受a的值啊???
tdcr5 2007-12-04
  • 打赏
  • 举报
回复
LS正解,MAIN中局部变量被当做引用转递参数传进f5,
而且编译器肯定经过了Name Returned Value 优化,
不然应该是三次构造,三次析构
maxx 2007-12-04
  • 打赏
  • 举报
回复
就这么和你说吧,你先要弄清楚拷贝构造函数和重载运算符=,在F5里这个临时对象是已经通过构造函数初始化了的,所以
F5()=a ;不会调你的拷贝函数,而重载运算符=是你的左值初始化后调用的!你可以再写个重载运算符=就知道了!!!
ckt 2007-12-04
  • 打赏
  • 举报
回复
你还没搞明白?

这里没有产生临时变量,直接用X()去初始化返回值的。

实际上,对于有返回值的函数调用,编译器会把返回值的地址压栈,
然后在return语句之前,初始化返回值

f5函数可能的伪码:
void f5(X& _rlt) // 返回值地址
{
_rlt.X::X(10, 11); // 初始化返回值
return;
}

具体的你可以查阅深度探索C++对象模型

mutable 2007-12-04
  • 打赏
  • 举报
回复
to andy_cai:
哈,是啊,我们看不见,但是通过构造函数,拷贝构造函数可以看到临时变量的产生啊
就像值传递的时候,形参是实参的副本,这副本就是一个临时变量,它保存在栈中。我们可以在构造函数中加入输出语句,看到这个临时变量构造出来了。
mutable 2007-12-04
  • 打赏
  • 举报
回复
constructor 0 是f5()函数体内X()产生的吧???
编译器明白对创建的对象没有其他需求,只是返回它,所以编译器直接
把这个对象创建在外部返回值的内存能单元。

之后发现要用到函数返回值在一个表达式中,编译器不是应该再构造一个临时变量来接受a的赋值吗???
一个是函数返回值,一个是临时变量
andy_cai 2007-12-04
  • 打赏
  • 举报
回复
我来回答下lz的疑问
我记得在thinking in C++里面有句话
大意是
求表达式的期间,要创建临时变量,进行构造和删除。不过这些,我们往往是看不见
是编译器的事情
ckt 2007-12-04
  • 打赏
  • 举报
回复
编译器不是应该创建一个临时对象保存f5()返回值的值,并接受a的赋值吗
-----------
是的

你调用了一次默认构造函数,constructor 0
就是去初始化f5返回值的
mutable 2007-12-04
  • 打赏
  • 举报
回复
to ckt1120:
这个我明白,这是返回值优化。

我有疑问的是求表达式f5()=a期间,编译器不是应该创建一个临时对象保存f5()返回值的值,并接受a的赋值吗???
ckt 2007-12-04
  • 打赏
  • 举报
回复

X f5()
{
return X();
/*
对这个语句,编译器明白对创建的对象没有其他需求,只是返回它,所以编译器直接
把这个对象创建在外部返回值的内存能单元,并没有去创建一个局部变量来返回.
*/
}
ryfdizuo 2007-12-04
  • 打赏
  • 举报
回复

X f5()
{
return X();
}

这个函数里面构造了一个X类的对象;但是当函数结束的时候对象并没有随之析构,而是再main结束的时候析构调的,显然这个对象具有全局性;
至于f5() = a;纯粹就是将一个对象付给另一个对象,系统提供了默认的operator=支持,当然了这里不会调用任何的函数,也没有什么临时对象;
从蓝田到元谋 2007-12-04
  • 打赏
  • 举报
回复
楼主可以试试:
将X f5()函数该为X& f5()后输出结果是:
constructor 10
constructor 0
destructor 0 //注意这里
destructor 10
先顶一个,我自己先想想


64,683

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧