http://www.zhihu.com/question/38049776/answer/74688351
初学C++, 看到书上及网上说函数返回值不能为指向函数局部变量的指针或者引用, 因为局部变量会在函数结束后销毁, 那么指向其位置的指针和引用就失效了, 有风险.
针对Deitel书上的习题, 写一个40位整数的四则运算, 在重载操作符的函数中我创建了局部变量来储存返回值, 然后返回引用. 程序运行正常, 编译阶段也没有提示有风险.
请问各位高手, 这是巧合吗?
类定义
加法的重载函数
运算结果, 可以看到在打印之前 局部变量就已经被销毁了...
Visual Studio Community 2015
谢谢!
========================================================================================
我的回答:
更新补充:
所谓不能返回局部变量,是指局部变量在栈空间中分配内存,函数返回时栈指针回退,当主调函数继续调用其它被调函数时,栈指针上移,上一次函数调用所分配的空间会被本次调用覆盖,如果此时再引用原来的局部变量就会出现不可预见的结果。
所以局部变量在函数返回时并不是被销毁而是相当于可被再次利用。
int& test1()
{
int n = 5;
return n;
}
void test2()
{
int b = 8;
}
int main()
{
int & i = test1();
std::cout<<i<<std::endl;
int & b = test1();
test2();
std::cout<<b<<std::endl;
int c = test1();
test2();
std::cout<<c<<std::endl;
return 0;
}
上面一段测试代码输出结果为5,8,5;
i实际为test1 中局部变量的别名, 当test1推出时,i 指向的内存中值未被覆盖,直接输出为5;
输出b 之前,因为调用了test2, 实际指向的内存空间已被覆盖为8,故输出为8;
c是一个新的变量,其值为5, 故输出为5;
======================================================================
目前实测的结论是:
将operator+ 重载为成员函数时,返回局部变量的引用现象和题主一样,不会报错;
将operator+ 声明为友元时,会导致运行时错误;
//研究下再来回答
PS. 一般而言,建议把算术和关系操作符定义为非成员函数,且重载操作符的含义尽量保持与内置内型的一致
测试代码如下:
class fuck_test
{
friend fuck_test& operator+(const fuck_test &,const fuck_test &);
friend std::ostream & operator<<(std::ostream &,const fuck_test &);
public:
//default constructor
fuck_test():i(0),s(""){ std::cout<<"default constructor of fuck_test is called"<<std::endl;}
//constructor
fuck_test(int p,const std::string s1):i(p),s(s1) { std::cout<<"constructor of fuck_test is called"<<std::endl;}
//copy constructor
fuck_test(const fuck_test & m):i(m.i),s(m.s) { std::cout<<"copy constructor of fuck_test is called"<<std::endl; }
~fuck_test() { std::cout<<"destructor of fuck_test is called"<<std::endl; }
// fuck_test& operator+(const fuck_test &);
fuck_test& operator=(const fuck_test & m) { std::cout<<"operator= of fuck_test is called"<<std::endl; i = m.i ; s = m.s ; return *this;}
private:
int i;
std::string s;
};
fuck_test& operator+(const fuck_test & f1,const fuck_test & f2)
{
std::cout<<"operator+ of fuck_test is called"<<std::endl;
fuck_test ret(f1);
ret.i += f2.i;
ret.s += f2.s;
return ret;
}
/*
fuck_test& fuck_test::operator+(const fuck_test & f2)
{
std::cout<<"operator+ of fuck_test is called"<<std::endl;
i += f2.i;
s += f2.s;
fuck_test ret(*this);
return ret;
}
*/
std::ostream & operator<<(std::ostream & o,const fuck_test & f)
{
o<<f.i<<"\t"<<f.s;
return o;
}
//test code
int main()
{
fuck_test f1(1,"test");
std::cout<<f1<<std::endl;
fuck_test f2(3,"helloWorld");
std::cout<<f2<<std::endl;
fuck_test f3;
f3 = f1 + f2;
std::cout<<f3<<std::endl;
return 0;
}