簡體   English   中英

我可以重用rvalue引用參數來返回右值引用嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM