簡體   English   中英

靜態轉換到右值引用和 std::move 之間有什么區別嗎

[英]is there any difference between static cast to rvalue reference and std::move

靜態演員的描述說

如果 new_type 是右值引用類型,則 static_cast 將表達式的值轉換為 xvalue。 這種類型的 static_cast 用於在 std::move 中實現移動語義。(C++11 起)

這是否確認以下內容是等效的?

(一種)

X x1;
X x2 = static_cast<X&&>(x1); 

(乙)

X x1;
X x2 = std::move(x1);

是的,有一個非常重要的區別: std::move記錄您想要做什么。 此外,演員表容易寫出錯誤,比如忘記了&或錯誤的類型X

可以看出, std::move輸入更少。

在 C++11 中, T&&是一個右值引用。 它們的行為類似於 C++ 98/03 中的左值引用。 他們的目標——成為搬家的候選人。 在 C++98 中,這個結構可以出現在引用折疊中。

std::move - 將表達式轉換為右值。 它可以被稱為rvalue_cast ,但不是。

原則上可以顯式轉換為T&&類型。 官方標准要花一些錢,但在ISO/IEC 14882:2011草案中有這樣的內容:

5.2.9 靜態轉換

8)

左值到右值 (4.1)、數組到指針 (4.2) 和函數到指針 (4.3) 的轉換應用於操作數....

從實用的角度來看,使用std::move更方便。

考慮這個例子:

#include <stdio.h>
#include <utility>

class A
{
public:
A () {printf ("A ()" "\n");}
A (const A &) {printf ("A (&)" "\n");}
A (A &&) {printf ("A (&&)" "\n");}
A (const A &&) {printf ("A (const &&)" "\n");}
~ A () {printf ("~ A ()" "\n");}
};


int main ()
{
const A obj;
A obj2 (std::move (obj)); // 1-st approach
A obj3 (static_cast <const A&&> (obj));  // 2-nd approach
}

對我來說,第一種方法是:

  • 更方便(您應該對const A&&A&&執行static_cast嗎?)
  • 更明確(我可以在文本編輯器中使用搜索來查找項目中的std::move
  • 不易出錯。

它們不是嚴格等效的。 std::move()的實現依賴於static_cast

template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }

它們的不同之處在於std::move()remove_reference來處理引用崩潰 (A) 和 (B) 不嚴格等效的示例:

// Set up different behavior for lvalue and rvalue.
class T {};
void func(T&& t) { std::cout << "rvalue captured.\n"; }
void func(T& t) { std::cout << "lvalue captured.\n"; }
// Example:
Using X = T&;
X x1;
X x2 = static_cast<X&&>(x1); // (A) "lvalue captured."
X x3 = std::move(x1);        // (B) "rvalue captured."

當 a 是右值時,您可以使用static_cast<A &&>(a) ,但不應使用std::move(a)
當您使用A && a = std::move(A()) ,您會得到一個懸空引用。

基本思想是不能通過“傳遞”來進一步延長臨時文件的生命周期:從臨時文件綁定的引用初始化的第二個引用不會影響其生命周期。

std::move的實現有點像

template <typename T>
constexpr decltype(auto) move(T && __t) noexcept  // when used in std::move(A()),
                                                  // the lifetime of the temporary object is extended by __t
{
    return static_cast<typename std::remove_reference<T>::type &&>(__t);  // a xvalue returned, no lifetime extension
}

auto && a = std::move(A());  // the anonymous object wiil be destructed right after this line

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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