我可以重用rvalue引用参数来返回右值引用吗?

Dan*_*rey 7 c++ operator-overloading rvalue-reference c++11

请考虑以下代码:

struct MyString
{
  // some ctors

  MyString& operator+=( const MyString& other ); // implemented correctly
};

MyString operator+( const MyString& lhs, const MyString& rhs )
{
  MyString nrv( lhs );
  nrv += rhs;
  return nrv;
}

MyString&& operator+( MyString&& lhs, const MyString& rhs )
{
  lhs += rhs;
  return std::move( lhs ); // return the rvalue reference we received as a parameter!
}
Run Code Online (Sandbox Code Playgroud)

这适用于以下用例

MyString a, b, c; // initialized properly
MyString result = a + b + c;
Run Code Online (Sandbox Code Playgroud)

但它创造了一个悬垂的参考

const MyString& result = a + b + c;
Run Code Online (Sandbox Code Playgroud)

现在,我理解为什么会这样,以及如何修复它(返回一个ravlue而不是rvalue引用)但我认为如果有人写上面的代码看起来像是在寻找麻烦,这是一个使用错误.是否有任何"规范"的现实示例,其中上述运算符返回右值引用是一个问题?为什么我应该总是从运营商那里返回一个rvalue有什么令人信服的理由?

Dan*_*rey 9

您正在寻找的示例是基于范围的for声明:

MyString a, b, c;
for( MyCharacter mc : a + b + c ) { ... }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,结果a + b + c绑定到引用,但嵌套的临时(由a + brvalue引用生成并作为rvalue引用返回(a + b) + c)在执行基于范围的for循环之前被销毁.

该标准定义了基于范围的for循环

6.5.4基于范围的语句[stmt.ranged]

1对于for表单的基于范围的声明

for (for-range-declaration :表达式)语句

range-init等同于括号括起来的表达式

( expression )

以及基于范围for的表单声明

for (for-range-declaration :braced-init-list )语句

range-init等同于braced-init-list.在每种情况下,基于范围的for陈述等同于

{
   auto && __range = range-init;
   for ( auto __begin = begin-expr,
              __end = end-expr;
         __begin != __end;
         ++__begin ) {
      for-range-declaration = *__begin;
      statement
   }
}
Run Code Online (Sandbox Code Playgroud)

请注意,auto && __range = range-init;会延长临时从返回的寿命范围,初始化,但它并没有嵌套的临时的寿命延长范围,初始化.


Ker*_* SB 5

你应该相信字符串自己的移动构造函数,而不是惹麻烦:

MyString operator+(MyString lhs, MyString rhs)
{
    lhs += std::move(rhs);
    return std::move(lhs);
}
Run Code Online (Sandbox Code Playgroud)

现在,这两个MyString x = a + b;MyString y = MyString("a") + MyString("b");提高工作效率.