#include "stdafx.h" #include<iostream> #include<ostream> #include<istream> int& rref() { int i = 11; return i; } int* rpot() { int j = 33; return &j; } int _tmain(int argc, _TCHAR* argv[]) { int &a = rref(); int *b = rpot(); std::cout<<"ref "<<a<<'\n'; std::cout<<"pot"<<*b<<'\n'; int c(2); std::cin>>c; return 0; }
如以上两个函数rref,rpot,分别返回指向局部变量的引用和指针。
如果在测试时,_tmain只有函数rref
int &a = rref(); std::cout<<"ref "<<a<<'\n';
结果为ref11正确
如果_tmain只有函数rpot
int *b = rpot(); std::cout<<"pot"<<*b<<'\n';
结果为pot33正确
但是如果同时出现
int _tmain(int argc, _TCHAR* argv[]) { int &a = rref(); int *b = rpot(); std::cout<<"ref "<<a<<'\n'; std::cout<<"pot"<<*b<<'\n'; int c(2); std::cin>>c; return 0; }
结果为
ref 33
pot1834244
出现错误。
逐步调试程序,
当程序运行到
int *b = rpot();
此时a为11正确。
但是当运行到
std::cout<<"ref "<<a<<'\n';
a = 33
b = 0x0030f914
运行到
std::cout<<"pot"<<*b<<'\n';
*b = 3209748
a = 3209748
通过更改函数rpot中j的值,可以看出当程序运行到
std::cout<<"ref "<<a<<'\n';
本来引用i的引用a却引用了 j 的值。
当函数返回引用时,没有复制返回值,而是返回对象本身。
返回引用的函数返回一个左值,这样的函数可以用在任何要求使用左值的地方。
不要返回局部变量的引用或指针,因为一旦函数结束,局部变量被释放,对局部变量的引用会指向不确定的内存,返回的指针变成了悬垂指针。
出现上述错误的原因很可能是因为调用rref结束后,分配给局部变量i的存储空间被释放,此时对局部对象的引用即a指向不确定的内存,在本程序中a仍指向这个内存。
当调用rpot时,因为局部变量i的存储空间被释放,该存储空间分给了局部变量j,此时值为33,所以运行
std::cout<<"ref "<<a<<'\n';
时,a为33.
但是接下来运行
std::cout<<"pot"<<*b<<'\n';
的结果无法解释。
请问两者直接是如何影响的?
如果是类的话会不会出现同样情况?
在《More effective c++》一书中,介绍vitual copy constructor时,派生类成员函数返回了局部变量的指针
virtual FirstCom * getCopy() const{ return new FirstCom(*this); }