C++返回对局部变量的引用

bli*_*egz 102 c++

如果必须返回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)

  • 美丽的解释。:hattip: 在第三个代码片段中,您正在删除 `int* p = func2(); delete p;` 现在,当你删除 'p' 时,是否意味着在函数 `func2()` 的定义“内部”分配的内存也被删除了? (2认同)
  • @Anisha Kaul:是的。内存在 `func2()` 内部分配,并在下一行释放到外部。不过,这是一种相当容易出错的处理内存的方式,就像我说的那样,您将改用 RAII 的某些变体。顺便说一句,您听起来像是在学习 C++。我建议选择 [一本很好的 C++ 入门书](http://stackoverflow.com/questions/388242) 来学习。此外,如果您有问题,可以随时在 Stack Overflow 上发布问题以供将来参考。评论并不是为了提出全新的问题。 (2认同)

小智 17

局部变量是堆栈中的内存,当您超出范围时,该内存不会自动失效.从功能更深的嵌套(内存中的堆栈更高),它可以非常安全地访问此内存.

一旦函数返回并结束,事情就变得危险了.通常,当您返回时,内存不会被删除或覆盖,这意味着该地址的内存仍然包含您的数据 - 指针似乎有效.

直到另一个函数构建堆栈并覆盖它.这就是为什么它可以工作一段时间 - 然后在一个特别深度嵌套的函数集或者具有非常大的或许多本地对象的函数再次到达堆栈内存之后突然停止运行的原因.

甚至可能会再次到达相同的程序部分,并使用新的函数变量覆盖旧的本地函数变量.所有这些都是非常危险的,应该严重劝阻. 不要使用指向本地对象的指针!