我可以重用右值引用形参来返回右值引用吗?
Can I reuse an rvalue reference parameter to return an rvalue reference?
考虑以下代码:
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;
现在,我明白了为什么会这样,以及如何修复它(返回一个值而不是一个右值引用),但我认为这是一个使用错误,如果有人写上面的代码看起来像它在自找麻烦。是否有任何"规范"的现实世界的例子,上面的操作符返回右值引用是一个问题?为什么我应该总是从操作符返回一个右值,一个令人信服的理由是什么?
您正在寻找的示例是基于范围的for
语句:
MyString a, b, c;
for( MyCharacter mc : a + b + c ) { ... }
在这种情况下,a + b + c
的结果被绑定到一个引用,但是嵌套的临时(由a + b
生成并由(a + b) + c
作为右值引用返回)在基于范围的for循环执行之前被销毁。
标准在
中定义了基于范围的for循环6.5.4基于范围的for语句[stmt.range]1对于形式为
的基于范围的for
语句
for (
for-range-declaration:
expression)
statement让range-init等价于用圆括号括起来的表达式
( expression )
和形式为
的基于范围的for
语句
for (
for-range-declaration:
braced-init-list)
statement让range-init等价于带括号的init-list。在每种情况下,基于范围的
for
语句都相当于{ auto && __range = range-init; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
注意, 与其自找麻烦,不如相信字符串自己的move构造函数: 现在auto && __range = range-init;
会延长从range-init返回的临时对象的生命周期,但是它不会延长range-init 内嵌套的临时对象的生命周期。MyString operator+(MyString lhs, MyString rhs)
{
lhs += std::move(rhs);
return std::move(lhs);
}
MyString x = a + b;
和MyString y = MyString("a") + MyString("b");
都有效地工作了
- 如何通过引用返回对象
- 函数如何使用引用返回所需的数字?
- 如何防止引用返回的私有结构的突变
- 如何在不使用临时变量的情况下取消引用返回指针的函数的返回值?
- 通过引用返回的变量的范围
- 对于具有引用返回类型的搜索算法,默认返回值应该是什么?
- 运算符重载C++类中的引用返回
- C++对象引用返回不同的值
- 解释通过从函数引用返回数组的语法
- 具有引用返回类型的重写方法上的协变返回类型无效
- 为什么在通过引用返回运算符分配时取消引用'this'指针?
- 为什么我在函数中使用引用并通过引用返回它仍然有效?
- 直接在 C++ 中将值分配给引用返回类型
- C++当您取消引用指向类对象的指针,然后将其作为引用返回时,是否可以对此引用调用方法
- 可以通过常量引用返回默认参数的值吗?
- 按值与右值引用返回
- 非常量引用返回函数在常量值返回函数上用作 r 值
- 当我使用按引用返回时,我不知道这些代码之间的区别
- 为什么通过引用返回向量比通过移动返回要快得多?
- 通过引用返回包含对象的向量