关于C++函数返回值的问题
请看下面的代码:#include<iostream.h>usingnamespacestd;classtest{public:test(intx=0):i(x){cout...
请看下面的代码:
#include<iostream.h>
using namespace std;
class test
{
public:
test(int x=0):i(x){cout<<"新建的该对象的地址为:"<<this<<endl;}
~test(){cout<<"析构地址为:"<<this<<"的对象"<<endl;}
int i;
};
int main()
{
test f();
cout<<"------1------"<<endl;
const test &b=f();
cout<<"------2------"<<endl;
cout<<"b.i="<<b.i<<endl;
system("pause");
return 0;
}
test f()
{
test a(7);
++a.i;
cout<<"a.i="<<a.i<<endl;
return a;
}
在该函数返回时,不是先按对象a的内容来创建一个临时对象么?然后析构对象a,那个临时对象因为在main函数中建立了引用,所以生命周期延长到了与对象b相同,问题是:为什么临时对象a在退出函数时没有被析构?
我的代码确实有些多余的地方,当初那样设计是想弄清楚到底构造或析构的是哪一个类对象。请弄清楚我的问题,我是问在函数 f 内创建的临时对象a,为什么在退出函数时没有被析构?还有为什么在函数返回值时没有按a来拷贝创建一个瞬间的无名对象?在主函数结束前,我加了一段:cout<<"&b="<<&b<<endl;
结果是b与a的地址相同。我之前的理解是b应该引用的是瞬间无名对象啊,而不是对象a 展开
#include<iostream.h>
using namespace std;
class test
{
public:
test(int x=0):i(x){cout<<"新建的该对象的地址为:"<<this<<endl;}
~test(){cout<<"析构地址为:"<<this<<"的对象"<<endl;}
int i;
};
int main()
{
test f();
cout<<"------1------"<<endl;
const test &b=f();
cout<<"------2------"<<endl;
cout<<"b.i="<<b.i<<endl;
system("pause");
return 0;
}
test f()
{
test a(7);
++a.i;
cout<<"a.i="<<a.i<<endl;
return a;
}
在该函数返回时,不是先按对象a的内容来创建一个临时对象么?然后析构对象a,那个临时对象因为在main函数中建立了引用,所以生命周期延长到了与对象b相同,问题是:为什么临时对象a在退出函数时没有被析构?
我的代码确实有些多余的地方,当初那样设计是想弄清楚到底构造或析构的是哪一个类对象。请弄清楚我的问题,我是问在函数 f 内创建的临时对象a,为什么在退出函数时没有被析构?还有为什么在函数返回值时没有按a来拷贝创建一个瞬间的无名对象?在主函数结束前,我加了一段:cout<<"&b="<<&b<<endl;
结果是b与a的地址相同。我之前的理解是b应该引用的是瞬间无名对象啊,而不是对象a 展开
3个回答
展开全部
至少在C++03中,并不一定会创建临时对象。这是由实现定义的。
ISO C++03:
3.10/5 The result of calling a function that does not return a reference is an rvalue.
......
8.5.3/5
......
— If the initializer expression is an rvalue, with T2 a class type, and “cv1 T1” is reference-compatible
with “cv2 T2,” the reference is bound in one of the following ways (the choice is implementation-defined):
— The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.
— A temporary of type “cv1 T2” [sic] is created, and a constructor is called to copy the entire
rvalue object into the temporary. The reference is bound to the temporary or to a sub-object
within the temporary.93) The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.
93) Clearly, if the reference initialization being processed is one for the first argument of a copy constructor call, an implementation must eventually choose the first alternative (binding without copying) to avoid infinite recursion.
PS1.对于非引用的对象类型,在ISO C++03 12.8/15中允许一个用返回值初始化对象(而不是这里的引用)时实现省略复制构造。
PS2.在新的标准中关于这里的“由实现定义”有变化。详见http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#391。
↑2011-3-30 19:47
----
简单来说,理解成被编译器优化掉就行了。
至于LS说的是另一回事,和LZ的问题看起来有相似之处但实际无关(不涉及返回自动存储期对象)。
ISO C++03:
3.10/5 The result of calling a function that does not return a reference is an rvalue.
......
8.5.3/5
......
— If the initializer expression is an rvalue, with T2 a class type, and “cv1 T1” is reference-compatible
with “cv2 T2,” the reference is bound in one of the following ways (the choice is implementation-defined):
— The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.
— A temporary of type “cv1 T2” [sic] is created, and a constructor is called to copy the entire
rvalue object into the temporary. The reference is bound to the temporary or to a sub-object
within the temporary.93) The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.
93) Clearly, if the reference initialization being processed is one for the first argument of a copy constructor call, an implementation must eventually choose the first alternative (binding without copying) to avoid infinite recursion.
PS1.对于非引用的对象类型,在ISO C++03 12.8/15中允许一个用返回值初始化对象(而不是这里的引用)时实现省略复制构造。
PS2.在新的标准中关于这里的“由实现定义”有变化。详见http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#391。
↑2011-3-30 19:47
----
简单来说,理解成被编译器优化掉就行了。
至于LS说的是另一回事,和LZ的问题看起来有相似之处但实际无关(不涉及返回自动存储期对象)。
追问
好像理解你所说的了,那么,假如我用的编译器没有设置优化的话,b引用的就是瞬间无名对象,而不是对象a,再同时析构a,对吧?
参考资料: 原创 + ISO/IEC 14882:2003 + Google
展开全部
#include<iostream.h>
class test
{
public:
test(int x=0):i(x)
{
cout<<"新建的该对象的地址为:"<<this<<endl;
}
~test()
{
cout<<"析构地址为:"<<this<<"的对象"<<endl;
}
int i;
};
int main()
{
test f();
cout<<"------1------"<<endl;
const test &b=f();
cout<<"------2------"<<endl;
cout<<"b.i="<<b.i<<endl;
return 0;
}
test f()
{
test a(7);
++a.i;
cout<<"a.i="<<a.i<<endl;
return a;
}
这个是没问题的,正确输出,不过你的代码确实认人匪姨所思
class test
{
public:
test(int x=0):i(x)
{
cout<<"新建的该对象的地址为:"<<this<<endl;
}
~test()
{
cout<<"析构地址为:"<<this<<"的对象"<<endl;
}
int i;
};
int main()
{
test f();
cout<<"------1------"<<endl;
const test &b=f();
cout<<"------2------"<<endl;
cout<<"b.i="<<b.i<<endl;
return 0;
}
test f()
{
test a(7);
++a.i;
cout<<"a.i="<<a.i<<endl;
return a;
}
这个是没问题的,正确输出,不过你的代码确实认人匪姨所思
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
与实参的问题
以一个简单的程序为例来说明
void MSwapa(int a,int b);//这 两个函数都是交换a,b的值
void MSwapb(int&a,int&b);
int main(){
int a=2;
int b=3;
MSwapa(a,b);
cout <<a<<" "<<b<<endl;
MSwapb(a,b);
cout <<a<<" "<<b<<endl;
return 0;
}
void MSwapa(int a,int b){
int tmp=a;
a=b;
b=tmp;
}
void MSwapb(int&a,int&b){
int tmp=a;
a=b;
b=tmp;
}
//运行结果是
2 3
3 2
虽然两个函数都是交换a,b的值
MSwapa(int a,int b)参数没有用引用,这样在MSwapa(int a,int b)内产生两个临时对象a和b,并且是你在main()函数中定义的int a,b的值分别赋给这两个临时变量,而MSwapa(int a,int b)只是将这两个临时对象的值交换了
所以cout<<a<<" "<<b<<endl的结果是没有交换的
MSapb(int&a,int&b)用了引用,它直接对你在main()中定义的int a,b这两个变量的值进行交换,所以cout<<a<<" "<<b<<endl的结果是a、b两值交换了的
以一个简单的程序为例来说明
void MSwapa(int a,int b);//这 两个函数都是交换a,b的值
void MSwapb(int&a,int&b);
int main(){
int a=2;
int b=3;
MSwapa(a,b);
cout <<a<<" "<<b<<endl;
MSwapb(a,b);
cout <<a<<" "<<b<<endl;
return 0;
}
void MSwapa(int a,int b){
int tmp=a;
a=b;
b=tmp;
}
void MSwapb(int&a,int&b){
int tmp=a;
a=b;
b=tmp;
}
//运行结果是
2 3
3 2
虽然两个函数都是交换a,b的值
MSwapa(int a,int b)参数没有用引用,这样在MSwapa(int a,int b)内产生两个临时对象a和b,并且是你在main()函数中定义的int a,b的值分别赋给这两个临时变量,而MSwapa(int a,int b)只是将这两个临时对象的值交换了
所以cout<<a<<" "<<b<<endl的结果是没有交换的
MSapb(int&a,int&b)用了引用,它直接对你在main()中定义的int a,b这两个变量的值进行交换,所以cout<<a<<" "<<b<<endl的结果是a、b两值交换了的
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询