2016-03-16 245 views
6

我有一個表示運行時上下文並構建樹的類,樹根保存在unique_ptr中。當建樹完成時,我想提取樹。這是它的外觀(不可運行,這不是一個問題,調試):std :: unique_ptr :: release()vs std :: move()

class Context { 
    private: 
    std::unique_ptr<Node> root{new Node{}}; 
    public: 
    // imagine a constructor, attributes and methods to build a tree 
    std::unique_ptr<Node> extractTree() { 
     return std::move(this->root); 
    } 
}; 

所以我用std::move()提取從Context實例的根節點。

但也有替代品使用std::move()例如爲:

std::unique_ptr<Node> extractTree() { 
    // This seems less intuitive to me 
    return std::unique_ptr<Node>{this->root.release()}; 
} 

std::move()最好的選擇?

+0

移動後需要從'this-> root'調用'reset'。你最好還是閱讀這個答案http://stackoverflow.com/a/20850223/555515 – neuront

+2

@neuront:不,你沒有。 –

+0

移動src後包含nullptr,重置是毫無意義的! – paulm

回答

4

你應該明確地使用第一個版本,因爲第二個版本基本上做的是第一個版本用更多的代碼和更少的可讀性所做的一切。

從哲學上講,第二個版本移動的唯一指針,沒有更多,沒有更多。那麼爲什麼要繞桌而不是使用已經存在的,更易讀和更慣用的std::unique_ptr(std::unique_ptr&&)

最後,如果您將來某處的智能指針將會保留服裝刪除者,第一個版本將確保刪除者移動以及第二個版本不會移動刪除者。我可以肯定地想象程序員使用release構建非服裝刪除器唯一指針脫離costum-deleter unique_pointer。通過移動semtantics,程序將無法編譯。

3

你在做什麼是危險的。一旦你呼叫getTree(),你不能再次調用它,這是從界面不清楚。您可能需要重新考慮您的設計(例如,shared_ptr可能會做得更好,或者將根存儲爲原始指針並手動處理重新分配)。

無論如何,使用std::move是兩個更好的選擇,如果你想堅持你的設計,因爲它使你的意圖更清晰。

編輯:顯然'不能'具有禁止在英語中的特殊含義我不知道。可以根據需要調用函數兩次或多次,但如果連續完成則不會返回指向有效對象的指針。

+0

第二次調用getTree()沒有問題。它只會返回一個空的'unique_ptr'。 –

+1

爲什麼你不能兩次調用'getTree()'?一旦根被移動,它被設置爲'nullptr',所以再次移動它會得到一個'nullptr',這對於一個空對象來說似乎是一個非常合理的行爲。 – nwp

+0

是不是爲什麼他建議你不要叫它兩次... – AngryDuck