右值引用總結

  1. 右值引用若不作爲函數參數使用,基本等於濫用

2.

std::vector<int>&& return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector &&rval_ref = return_vector();
這段代碼會造成運行時錯誤,主要原因是右值引用實際上也只是一個與某個對象綁定的別名,
而這段代碼中的rval_ref綁定到的目標是return_vector返回的一個從tmp中由move剝離出的臨時對象,這個臨時對象隨着return_vector的調用結束也被銷燬,如果後面代碼中對rval_ref的會引起運行時錯誤

3.
a=std::move(b)
如果移動語義只是實現了簡單的交換,那麼交換之後的效果僅僅是a和b兩個變量名持有的對象的互換,沒有東西被銷燬.當然a之前持有的對象最終會被銷燬,也就是說當b離開作用域之後,除非是b又和別的對象進行了移動操作,在這種情況下a之前持有的對象再次被傳遞.因此,對於拷貝賦值運算符的實現者來說他們並不知道a以前持有的對象何時會被銷燬,所以從某種意義上來說此時我們的析構是不確定的,一個變量已經通過賦值操作被覆蓋了,但是這個變量之前持有的對象依然在內存的某個地方,對於在銷燬時對別處代碼的執行沒有副作用的對象來說這當然沒問題,但是如果對象在銷燬時有副作用,比如在析構函數中released a lock , 這很可能出現難以查找的bug,因此在編寫那些進行銷燬時具有副作用的對象的用右值引用重載的拷貝賦值運算符時要顯示執行那些副作用操作以清理現場,防止產生莫名其妙的bug

X& X::operator=(X&& rhs)
{
    // Perform a cleanup that takes care of at least those parts of the destructor that have side effects
    // Be sure to leave the object in a destructible and assignable state.

    // move semantics : exchange content between this and rhs    [ swap(*this,rhs) ]

    return *this;
}
    4.
void foo(X&& x)
{
  X anotherX = x;
  // ...
}

假設X實現了拷貝構造和移動構造,那麼在構造anotherX時使用的是哪一種構造?
很顯然參數是右值引用,但其實在用這個右值引用的參數構造anotherX時用的是拷貝構造而不是移動構造,原因是:
① 在執行完 X anotherX = x ; 之後,形參x still in the scope !! 這樣如果後後面的代碼再用到x那就很危險了,因爲移動構造根本就不保證移動之後rhs裏面有什麼東西,它只保證rhs有效以及能被安全析構,
② 移動構造被調用的情況有兩種,rhs是一個prvalue,或者是xrvalue (std::move(左值)) , 而這裏的形參x是具名的,雖然他是一個右值引用但它本身其實是個左值,

綜上,在構造anotherX時調用的是拷貝構造

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章