[英]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;
現在,我理解為什么會這樣,以及如何修復它(返回一個ravlue而不是rvalue引用)但我認為如果有人寫上面的代碼看起來像是在尋找麻煩,這是一個使用錯誤。 是否有任何“規范”的現實示例,其中上述運算符返回右值引用是一個問題? 為什么我應該總是從運營商那里返回一個rvalue有什么令人信服的理由?
您要查找的示例是基於范圍的for
語句 :
MyString a, b, c;
for( MyCharacter mc : a + b + c ) { ... }
在這種情況下, a + b + c
的結果綁定到引用,但嵌套的臨時(由a + b
生成並作為右值引用返回(a + b) + c
)在基於范圍的基礎上被銷毀循環執行。
該標准定義了基於范圍的for循環
6.5.4基於范圍的語句[stmt.ranged]
1對於基於范圍
for
形式的語句
for (
range-declaration:
expression)
語句讓range-init等同於括號括起來的表達式
( expression )
而對於基於范圍
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 } }
請注意, auto && __range = range-init;
將延伸的臨時從范圍-INIT返回的壽命,但是它不嵌套的臨時的壽命延長范圍-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");
有效地工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.