我可以重用的右值引用参数返回右值的参考?(Can I reuse an rvalue referen

2019-09-01 04:00发布

考虑下面的代码:

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!
}

这适用于以下用例

MyString a, b, c; // initialized properly
MyString result = a + b + c;

但它创造了一个悬空参考

const MyString& result = a + b + c;

现在,我明白为什么,以及如何解决它(返回ravlue而不是右值引用的),但我认为这是一个用法错误,如果有人写上面的代码看起来是自找麻烦。 是否有任何“规范”真实世界的例子,其中上面的操作返回一个右值引用是一个问题吗? 什么是令人信服的理由,为什么我应该总是返回从运营商的右值?

Answer 1:

你正在寻找的例子是一个基于范围for语句

MyString a, b, c;
for( MyCharacter mc : a + b + c ) { ... }

在这种情况下的结果a + b + c被绑定到一个参考,但嵌套临时(由产生a + b并返回由右值参考(a + b) + c )的基于范围之前被破坏循环执行。

该标准定义了基于范围为循环中

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

1对于基于范围for形式的语句

for ( 用于范围声明 : 表达式 ) 语句

范围-INIT相当于用括号包围的表达

( expression )

而对于基于范围for形式的声明

for ( 换范围声明 : 支撑-初始化列表 ) 声明

范围-INIT等同于支撑-初始化列表 。 在每一种情况下,基于范围for语句相当于

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

需要注意的是auto && __range = range-init; 将延伸的临时从范围-INIT返回的寿命,但是它不嵌套的临时的寿命延长范围-INIT内部



Answer 2:

相反,自找麻烦,你应该相信字符串自己的移动构造函数:

MyString operator+(MyString lhs, MyString rhs)
{
    lhs += std::move(rhs);
    return std::move(lhs);
}

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



文章来源: Can I reuse an rvalue reference parameter to return an rvalue reference?