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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4643713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:02:03  来源:igfitidea点击:

C++ Returning reference to local variable

c++

提问by blitzkriegz

Is the following code (func1()) correct if it has to return i? I remember reading somewhere that there is a problem when returning reference to a local variable. How is it different from func2()?

如果必须返回 i,以下代码 (func1()) 是否正确?我记得在某处读到返回对局部变量的引用时出现问题。它与 func2() 有什么不同?

int& func1()
{
    int i;
    i = 1;
    return i;
}

int* func2()
{
    int* p;
    p = new int;
    *p = 1;
    return p;
}

回答by In silico

This code snippet:

此代码片段:

int& func1()
{
    int i;
    i = 1;
    return i;
}

will not work because you're returning an alias (a reference) to an object with a lifetime limited to the scope of the function call. That means once func1()returns, int idies, making the reference returned from the function worthless because it now refers to an object that doesn't exist.

将不起作用,因为您将别名(引用)返回到对象的生命周期仅限于函数调用的范围。这意味着一旦func1()返回,就int i死了,使得从函数返回的引用变得毫无价值,因为它现在引用了一个不存在的对象。

int main()
{
    int& p = func1();
    /* p is garbage */
}

The second version does work because the variable is allocated on the free store, which is not bound to the lifetime of the function call. However, you are responsible for deleteing the allocated int.

第二个版本确实有效,因为变量是在自由存储上分配的,它不受函数调用的生命周期的约束。但是,您有责任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
}

Typically you would wrap the pointer in some RAIIclass and/or a factory function so you don't have to deleteit yourself.

通常,您会将指针包装在某个RAII类和/或工厂函数中,这样您就不必delete自己处理了。

In either case, you can just return the value itself (although I realize the example you provided was probably contrived):

在任何一种情况下,您都可以返回值本身(尽管我意识到您提供的示例可能是人为的):

int func3()
{
    return 1;
}

int main()
{
    int v = func3();
    // do whatever you want with the returned value
}

Note that it's perfectly fine to return big objects the same way func3()returns primitive values because just about every compiler nowadays implements some form of return value optimization:

请注意,以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();    
}

Interestingly, binding a temporary to a constreference is perfectly legal C++.

有趣的是,将临时对象绑定到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();  
}

回答by Pica

A local variable is memory on the stack, that memory is not automatically invalidated when you go out of scope. From a Function deeper nested (higher on the stack in memory), its perfectly safe to access this memory.

局部变量是堆栈上的内存,超出范围时该内存不会自动失效。从嵌套更深的函数(内存中堆栈的更高位置),访问此内存是完全安全的。

Once the Function returns and ends though, things get dangerous. Usually the memory is not deleted or overwritten when you return, meaning the memory at that adresss is still containing your data - the pointer seems valid.

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

Until another function builds up the stack and overwrites it. This is why this can work for a while - and then suddenly cease to function after one particularly deeply nested set of functions, or a function with really huge sized or many local objects, reaches that stack-memory again.

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

It even can happen that you reach the same program part again, and overwrite your old local function variable with the new function variable. All this is very dangerous and should be heavily discouraged. Do not use pointers to local objects!

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

回答by David Sumich

A good thing to remember are these simple rules, and they apply to both parameters and return types...

值得记住的是这些简单的规则,它们适用于参数和返回类型......

  • Value - makes a copy of the item in question.
  • Pointer - refers to the address of the item in question.
  • Reference - is literally the item in question.
  • 价值 - 制作相关项目的副本。
  • 指针 - 指的是相关项目的地址。
  • 参考 - 字面上是有问题的项目。

There is a time and place for each, so make sure you get to know them. Local variables, as you've shown here, are just that, limited to the time they are locally alive in the function scope. In your example having a return type of int*and returning &iwould have been equally incorrect. You would be better off in that case doing this...

每个人都有时间和地点,所以一定要了解他们。正如您在此处显示的那样,局部变量仅限于它们在函数作用域中局部存在的时间。在您的示例中,返回类型为int*和 返回&i同样不正确。在那种情况下你会更好地这样做......

void func1(int& oValue)
{
    oValue = 1;
}

Doing so would directly change the value of your passed in parameter. Whereas this code...

这样做会直接更改传入参数的值。而这段代码...

void func1(int oValue)
{
    oValue = 1;
}

would not. It would just change the value of oValuelocal to the function call. The reason for this is because you'd actually be changing just a "local" copy of oValue, and not oValueitself.

不会。它只会将oValuelocal的值更改为函数调用。这样做的原因是因为您实际上只是在更改 的“本地”副本oValue,而不是oValue其本身。