返回一个本地对象右值引用,对还是错?

时间:2015-03-09 11:25:40

标签: c++ c++11

我看到一旦返回一个本地对象,编译器将采用返回值优化。(RVO,NRVO)。

  

标准祝福RVO的部分继续说,如果   满足RVO的条件,但编译器选择不执行   复制省略,返回的对象必须被视为右值。

所以我们只写这样的代码:

Widget makeWidget() 
{
 Widget w;
 …
 return w;//never use std::move(w);
}

我从未见过有人写过这样的代码:

Widget&& makeWidget()
{
 Widget w;
 …
 return std::move(w); 
}

我知道返回本地对象的左值引用总是错误的。 那么,返回本地对象的右值引用也是错误的?

4 个答案:

答案 0 :(得分:23)

返回对本地自动变量的引用总是错误的。当函数返回时,变量将被销毁,因此对引用的任何使用都将给出未定义的行为。

它是右值还是左值参考没有区别。

答案 1 :(得分:4)

当函数返回时,本地对象已被释放。

如果写这样的代码:

Widget&& makeWidget() 
{
 Widget w;
 …
 return std::move(w);
}

因此,请考虑以下三段代码:

<强>首先

Widget&& w= makeWidget();//w is a dangling reference,variable will be destroyed when the function returns

<强>第二

void foo(Widget&& w){...}//w is a dangling reference too

foo(makeWidget());

<强>第三

void foo(Widget w){...}//OK,will copy it

foo(makeWidget());

所以回答错了。

并注意:

Rvalue引用可用于延长可修改临时值的生命周期(注意,对const的左值引用也可以延长生命周期,但它们不可修改)

  

每当引用绑定到临时或基础子对象时   一个临时的,临时的生命周期延长到匹配   参考的生命周期,包含以下例外

     
      
  • 一个临时绑定到return语句中函数的返回值不会被扩展:它会在结束时立即销毁   返回表达式。此类函数始终返回悬空参考。

  •   
  • 存在于函数调用中的引用参数的临时绑定,直到包含该参数的完整表达式结束   函数调用:如果函数返回一个引用,则该函数寿命更长   完整的表达,它成为一个悬垂的参考。

  •   
  • 临时绑定到new-expression中使用的初始值设定项中的引用,直到包含完整表达式的结尾为止   那个new-expression,不像初始化对象那么长。如果初始化对象超出完整表达式,则其引用成员   成为一个悬垂的参考。

  •   
Widget&& makeWidget(){

  return Widget(123);//error
}

答案 2 :(得分:3)

是的,这是错的。没有引用生命周期扩展,因此引用引用了一个被破坏的值,并且它(几乎) 1 的任何使用都是未定义的行为。你不应该返回悬空引用或指针。


1 decltype并没有真正使用,但它也不是UB。所以就是这样。存储对它的引用也不是UB。也没用。

答案 3 :(得分:2)

不幸的是Widget w;在堆栈上,当您将引用传递给另一个函数时,w将被销毁...按值传递对象将保存对象不被破坏。 / p>