+ -
当前位置:首页 → 问答吧 → C++引用问题

C++引用问题

时间:2011-12-07

来源:互联网

#include<iostream>
using namespace std;
class A
{
public:
  A(int i){cout << "执行构造函数创造一个对象\n";x=i;}
  A(A&a){x=a.x;cout << "执行复制构造函数创建一个对象\n";}
  ~A(){cout << "执行析构函数释放一个对象\n";}
  int get(){return x;}
 private:
  int x;
};
A func()
{
  cout << "跳转到func函数中:\n";
  A a(23);
  return a;
}
int main()
{
  A &r=func();
  cout << "对象a的副本的地址:" << &r << endl;
  cout << r.get() << endl;
  return 0;

}
编译器报错:
\we\main.cpp|21|error: invalid initialization of non-const reference of type 'A&' from a temporary of type 'A'|
求大侠帮忙,看看那里错了?

作者: q243021856   发布时间: 2011-12-07

A &r=func();

他的意思是这里有错,func()返回的是一个临时对象,一个临时对象不能被一个非const 的引用绑定。
他是这么说的。

作者: mingliang1212   发布时间: 2011-12-07

vs2010编译通过,能正常输出呀。

作者: moonclock   发布时间: 2011-12-07

对象a的作用范围只能在func()中,出了func()后a就消亡了,所以引用会出错

作者: huai_f   发布时间: 2011-12-07

vc能便已通过,在codeblocks上编译就不行啦

作者: q243021856   发布时间: 2011-12-07

可是a消亡了,不是函数返回的时候还会产生一个副本吗

作者: q243021856   发布时间: 2011-12-07

引用 5 楼 q243021856 的回复:

可是a消亡了,不是函数返回的时候还会产生一个副本吗


是的,但是那个副本是临时的(通常用一次后就析构了)。而现在A &r = 临时变量; 也就是说r是一个临时变量(本尊)的别名(化身),但是这个操作完成后,那个临时变量就不存在了,本尊都不存在,化身也就木有任何意义了。

作者: pathuang68   发布时间: 2011-12-07

你的理解正确。

回到你的问题,关于出错的原因:函数func返回值是一个A类型的临时变量,C++是不允许一个non-const-reference绑定到一个临时变量的。MSVC如果允许的话那就是不符合标准。

顺便提一下,如果是non-const reference绑定到临时变量的话,后者的生命周期是引用变量的周期。

引用 5 楼 q243021856 的回复:

可是a消亡了,不是函数返回的时候还会产生一个副本吗

作者: tonywearme   发布时间: 2011-12-07

引用 5 楼 q243021856 的回复:
可是a消亡了,不是函数返回的时候还会产生一个副本吗


 A &r=func();

你的编译器认为,临时对象是不可以更改的。所以临时对象只能被const 引用绑定。如下:
const A& r= func();

作者: mingliang1212   发布时间: 2011-12-07

刚才打错一个字,应该是:

顺便提一下,如果是const reference绑定到临时变量的话,后者的生命周期是引用变量的周期。

引用 7 楼 tonywearme 的回复:

你的理解正确。

回到你的问题,关于出错的原因:函数func返回值是一个A类型的临时变量,C++是不允许一个non-const-reference绑定到一个临时变量的。MSVC如果允许的话那就是不符合标准。

顺便提一下,如果是non-const reference绑定到临时变量的话,后者的生命周期是引用变量的周期。

引用 5 楼 q243021856 的回复:

可是a消亡了……

作者: tonywearme   发布时间: 2011-12-07

可是书上说:临时变量的生命期不会少于那个引用变量,为什么楼上的说“后者的生命周期就是引用的变量的生命期呢”

作者: q243021856   发布时间: 2011-12-07

什么是const reference?

作者: q243021856   发布时间: 2011-12-07

严格意义上来说,临时变量的生命期大于等于引用变量,前面没有说清楚。

引用 10 楼 q243021856 的回复:

可是书上说:临时变量的生命期不会少于那个引用变量,为什么楼上的说“后者的生命周期就是引用的变量的生命期呢”

作者: tonywearme   发布时间: 2011-12-07

就是引用前加了const:

const A& r= func();

引用 11 楼 q243021856 的回复:

什么是const reference?

作者: tonywearme   发布时间: 2011-12-07

那什么情况下会像楼上那样用const A& r = func();

作者: q243021856   发布时间: 2011-12-07

引用 10 楼 q243021856 的回复:

可是书上说:临时变量的生命期不会少于那个引用变量,为什么楼上的说“后者的生命周期就是引用的变量的生命期呢”


那样的写法,可以理解为:引用r就是临时变量

作者: pathuang68   发布时间: 2011-12-08

引用 14 楼 q243021856 的回复:
那什么情况下会像楼上那样用const A&amp; r = func();


没有必要用const A& r = func();
这样的写法,应该用 A r = func();代替。
引用一般在函数参数传递的时候常用。其他地方一般不用,除非变量名字很长之类的无聊原因。

作者: mingliang1212   发布时间: 2011-12-08

如果这样写const A& = func();错误更多了!

作者: q243021856   发布时间: 2011-12-08

上述代码在vc2008中编译运行均无错误。
不过本人认为:
A &r=func();
上述语句如果改为A r = func();或许lz的编译器不会出错。
虽然func()返回的是一个临时对象,但是A r = func();执行的是一个拷贝传值的方式,所以应该不会出错(在《Thingking in C++》第一卷中的引用一章也用该模式,并给出了原理,p253,最近刚好看到这一部分)。
引用必须和存储单元联系,即访问引用时,实际就是在访问那个存储单元,所以本人怀疑func()返回的对象的隐藏指针虽然被销毁了,可实际的地址中的内容未被覆盖,故引用后的对象还是可用。
当然,应该尽量避免此种情况的发生。

作者: likid1412   发布时间: 2011-12-08

热门下载

更多