2015-04-08 51 views
4

說=運營商,我有一個類:移動構造函數和共享指針

class GameObject ///header file 
{ 
    .... 
    std::shared_ptr<Transform> transform; 
} 
///cpp file 
//Copy Ctor 
GameObject::GameObject(const GameObject& rhs) 
    :transform(rhs.transform) 
{} 
//Move CTor 
GameObject::GameObject(GameObject&& rhs) 
    :transform(std::move(rhs.transform)) 
{} 
  1. 這是正確的,以創建具有shared_ptr的成員變量的類的移動構造函數?或者我需要撥打rhs.transform.reset()在移動後取消分配rhs?
  2. 複製構造函數如何?
  3. 大概,複製和移動任務看起來與ctors基本相同,最後只有return *this
+0

你在這裏的拷貝構造函數只是一個淺拷貝,它可能是也可能不是你想要的。 – dwcanillas

+0

@dwcanillas沒有發生淺拷貝。 – 0x499602D2

+0

@ 0x499602D2我們不是在看構造函數9嗎? http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr – dwcanillas

回答

9

您的副本和移動構造函數等價於隱式構造函數。刪除它們。您不需要明確寫出它們,因爲std::shared_ptr的複製和移動構造函數正確執行了這兩個操作。

或者是否需要撥打rhs.transform.reset()在移動後取消分配rhs

沒有,移動,從對象將移動後失去所有權:

shared_ptr(shared_ptr&& r) noexcept; 
template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept; 

備註:第二個構造函數不得參加重載除非Y*可轉換爲T*

效果:移動 - 從r構造一個shared_ptr實例。 後續條件:*this應包含舊值rr應爲空。 r.get() == nullptr

至於複製和移動賦值操作符,它們也是等價的。移動分配將正確地轉移所有權,並且複製構造函數將執行淺度複製,以便兩個shared_ptr都擁有所有權。

如果淺拷貝(共享所有權)真的是你想要的,那麼shared_ptr是正確的工具。否則,我會建議使用unique_ptr,如果你想實施獨特的所有權

1
  1. 此代碼是正確的。如果GameObject是可移動的,則移動transform是非常合理的。 shared_ptr移動構造函數將在這裏爲您做正確的事情 - 它將轉讓Transform的所有權。你不需要調用reset(),這是一個無關的操作 - 你應該只需要依賴你的成員對象的移動構造函數來正確實現,這對於shared_ptr而言是最確定的。

  2. 會員明智的副本是正確的,並且shared_ptr會正確地爲您複製。

  3. 是的。

請注意,如果您的類完全由實現了所有正確操作符的對象組成,則不需要自己編寫它們。默認的構造函數和賦值操作符已經完成了成員方式的複製/移動,這是完全正確的。不必編寫任何基本5個功能叫做Rule of Zero

class GameObject { 
    std::shared_ptr<Transform> transform; 
    std::shared_ptr<SomethingElse> foo; 
}; 

GameObject obj = ...; 
GameObject obj2 = obj;    // correct by default 
GameObject obj3 = std::move(obj2); // correct by default 
0
  1. 的標準,爲shared_ptr此舉構造離開原來的shared_ptr空的,所以不需要reset()電話。

  2. 您寫的複製構造函數將在幾個GameObject之間共享一個Transform對象。也許這是你想要的。如果沒有,你需要類似transform(new Transform(*rhs.transform))。基本上,但是你應該使用賦值而不是構造成員(因爲後者在語法上是不合法的)。不過,要小心代碼重複。另一種方法可以是使用像複製和交換成語委派工作回到構造函數:

    GameObject &operator=(const GameObject &rhs) { 
        GameObject tmp(rhs); 
        tmp.swap(*this); 
        return *this; 
    } 
    

此外,如已被其他幾個人被已經指出的那樣,如果你的構造函數和分配與編譯器生成的默認值相同(正如他們當前所做的那樣),移除它們更短且更安全,只需使用默認值即可。