我可以重用右值引用参数来返回右值引用吗? [英] Can I reuse an rvalue reference parameter to return an rvalue reference?

查看:140
本文介绍了我可以重用右值引用参数来返回右值引用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

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;

但是它为...创建了悬挂的参考

But it creates a dangling reference for

const MyString& result = a + b + c;

现在,我了解了为什么以及如何解决(返回ravlue而不是右值引用),但是如果有人将上面的代码写成上面的代码,则我认为它是使用错误,因为它看起来像是在自找麻烦.是否有任何规范"的实际示例,其中上述运算符返回右值引用是一个问题?为什么我应该始终从运算符返回右值是什么有说服力的原因?

Now, I understand why that is and how to fix it (returning an ravlue instead of an rvalue reference) but I consider it a usage error if someone writes the above as the code looks like it is asking for trouble. Is there any "canonical" real-world example where the above operator returning a rvalue reference is a problem? What is a convincing reason why I should always return an rvalue from operators?

推荐答案

您要查找的示例是基于基于范围的for语句:

The example you are looking for is a range-based for statement:

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

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

In this case the result of a + b + c is bound to a reference, but the nested temporary (generated by a + b and returned as an rvalue reference by (a + b) + c) is destroyed before the range-based for loop is executed.

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

The standard defines range-based for loops in

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

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

6.5.4 The range-based for statement [stmt.ranged]

1 For a range-based for statement of the form

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

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

let range-init be equivalent to the expression surrounded by parentheses

( expression )

以及形式为基于范围的for语句

and for a range-based for statement of the form

for ( 用于范围声明 : 括号初始化列表 ) 声明

range-init 等效于 braced-init-list .在每种情况下,基于范围的for语句等效于

let range-init be equivalent to the braced-init-list. In each case, a range-based for statement is equivalent to

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

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

Note that auto && __range = range-init; would extend the lifetime of a temporary returned from range-init, but it does not extend the lifetime of nested temporaries inside of range-init.

这篇关于我可以重用右值引用参数来返回右值引用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆