结论:
(1)不能返回局部变量的引用给一个引用变量。
(2)但是如果返回引用给一个相关的非引用变量的话是可以的.
原因如下:
问题一:
返回一个局部变量的引用。如:
int& ABC()
{
int n = 5;
return n;
}
void main()
{
int x;
x=ABC();
cout<<x<<endl;
}
为什么这里能接收到 返回局部变量的引用呢?局部变量n没有被销毁吗?
解释:
(1)
所谓不能返回局部变量,是指局部变量在栈空间中分配内存,函数返回时栈指针回退,当主调函数继续调用其它被调函数时,栈指针上移,上一次函数调用所分配的空间会被本次调用覆盖,如果此时再引用原来的局部变量就会出现不可预见的结果。
所以局部变量在函数返回时并不是被销毁而是相当于可被再次利用。所以如果第一题你在cout<<x<<endl;前调用一个函数,此函数大量分配局部变量,后面的输出值必变!
(2)
如果把返回的引用赋给变量是无论怎么都不会变的,因为返回时进行了变量的复制(不一定是调用构造函数),要改变其实我上面已经说了只要在cout<<X前调用一个函数且函数内定义了局部变量即可:
int x= ABC();
test();
cout<<x;
void test()
{
int a=8;
}
这样X的输出将是8,下题类似不再举例.
另外一种解释:
函数退出时局部变量出栈,对象肯定是销毁了。销毁指的是将那块内存标为空闲供其它变量使用,而该内存上的值仍然存在。释放后那块内存并不是马上就被其他地方占用,根据实际情况起码会空闲一会,可能是一瞬间。如果你的程序较复杂,那这块内存可能很快就再次被使用,如果程序很简单,可能在很长一段时间内都是空闲。所以在函数返回后将变量的值马上赋值给另外一个变量,局部变量已经销毁了,这块内存上的值还没来得及被修改,所以你的外部变量获得了一个正确的值。
所以你的结果正确并不代表变量没有被销毁。就像第一种解释一样,如果第一题你在cout<<x<<endl;前调用一个函数,此函数大量分配局部变量,即占用那段内容,其值必变,这已经经过我验证。
用引用和用对象的区别在于,对象需要构造,而引用只是个别名,类似指针(引用在C++底层其实就是指针),故如果将返回引用的函数赋值给某个引用是不行的,因为它指向内存可能已经被其他内容占据了。而如果把返回的引用赋给变量是可以的,因为返回时进行了变量的复制。
看如下例子:
#include <iostream>
using namespace std;
int& fun()
{
int i = 100;
return i;
}
void test()
{
int i = 0;
}
int main()
{
// int& a = fun();//返回的是局部变量i的引用,即地址,有问题。相当于int &a = i;
int a=fun();//返回的是局部变量i的值,没有问题,相当于int a = i;
// test(); //此处由于fun后没有其他代码,所以输出值没问题,若将test函数打开,则a的值会有问题。
cout << a << endl;
return 0;
}
例子2:
#include <iostream>
using namespace std;
class Complex
{
public:
Complex(double r=0,double i=0)
{
real=r;imag=i;
}
Complex(const Complex& c);
Complex& operator+(Complex &);
void display( );
private:
double real, imag;
};
Complex::Complex(const Complex& c)
{
real=c.real;
imag=c.imag;
}
Complex& Complex::operator+(Complex &c2)
{
int a=1;
Complex c;
c.real=real+c2.real;
c.imag=imag+c2.imag;
return c;
}
void Complex::display( )
{
int xxxx=1;
cout <<"(" <<real <<"+" <<imag <<"i)" <<endl;
}
int main( )
{
double x, y;
cin>>x>>y;
Complex comp1(x,y),comp2(y,x),comp3;
comp1.display( );
comp2.display( );
comp3=comp1.operator+(comp2); //用对象 接收函数返回的引用 是正确的
Complex& p=comp1.operator+(comp2); //用对象的引用 接收函数返回的引用 是错误的
p.display();
comp3.display();
return 0;
}