如果必须返回i,以下代码(func1())是否正确?我记得在某处读到返回对局部变量的引用时存在问题.它与func2()有什么不同?
int& func1()
{
int i;
i = 1;
return i;
}
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
Run Code Online (Sandbox Code Playgroud)
In *_*ico 174
此代码段:
int& func1()
{
int i;
i = 1;
return i;
}
Run Code Online (Sandbox Code Playgroud)
因为你将一个别名(一个引用)返回给一个生命周期限制在函数调用范围内的对象,所以不会起作用.这意味着一旦func1()
返回,int i
就会死掉,使得从函数返回的引用毫无价值,因为它现在引用了一个不存在的对象.
int main()
{
int& p = func1();
/* p is garbage */
}
Run Code Online (Sandbox Code Playgroud)
第二个版本确实有效,因为变量是在免费存储上分配的,它不受函数调用的生命周期的约束.但是,您负责delete
分配int
.
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
int main()
{
int* p = func2();
/* pointee still exists */
delete p; // get rid of it
}
Run Code Online (Sandbox Code Playgroud)
通常,您可以将指针包装在某些RAII类和/或工厂函数中,这样您就不必delete
自己动手了.
在任何一种情况下,您都可以返回值本身(虽然我意识到您提供的示例可能是人为的):
int func3()
{
return 1;
}
int main()
{
int v = func3();
// do whatever you want with the returned value
}
Run Code Online (Sandbox Code Playgroud)
请注意,以相同的方式func3()
返回原始值返回大对象是完全正确的,因为现在几乎每个编译器都实现某种形式的返回值优化:
class big_object
{
public:
big_object(/* constructor arguments */);
~big_object();
big_object(const big_object& rhs);
big_object& operator=(const big_object& rhs);
/* public methods */
private:
/* data members */
};
big_object func4()
{
return big_object(/* constructor arguments */);
}
int main()
{
// no copy is actually made, if your compiler supports RVO
big_object o = func4();
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,将临时绑定到const引用是完全合法的C++.
int main()
{
// This works! The returned temporary will last as long as the reference exists
const big_object& o = func4();
// This does *not* work! It's not legal C++ because reference is not const.
// big_object& o = func4();
}
Run Code Online (Sandbox Code Playgroud)
小智 17
局部变量是堆栈中的内存,当您超出范围时,该内存不会自动失效.从功能更深的嵌套(内存中的堆栈更高),它可以非常安全地访问此内存.
一旦函数返回并结束,事情就变得危险了.通常,当您返回时,内存不会被删除或覆盖,这意味着该地址的内存仍然包含您的数据 - 指针似乎有效.
直到另一个函数构建堆栈并覆盖它.这就是为什么它可以工作一段时间 - 然后在一个特别深度嵌套的函数集或者具有非常大的或许多本地对象的函数再次到达堆栈内存之后突然停止运行的原因.
甚至可能会再次到达相同的程序部分,并使用新的函数变量覆盖旧的本地函数变量.所有这些都是非常危险的,应该严重劝阻. 不要使用指向本地对象的指针!