2016-03-16 17 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); 
    } 
}; 

は、だから私はContextインスタンスからルートノードを抽出するためにstd::move()を使用しました。

は、しかし、例えば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

最初のバージョンは2番目のバージョンと同じですが、最初のバージョンでは基本的にすべてのコードが実行されます。

哲学的に言えば、第2のバージョンは、をユニークなポインタに移動します。なぜ既存の、より読みやすく、より慣用的なものを使用するのではなく、テーブルの周りを回るのですかstd::unique_ptr(std::unique_ptr&&)

最後に、将来どこかのスマートポインタがコスチュームデリーターを保持する場合、最初のバージョンでは削除者も移動し、2番目のバージョンでは削除者は移動しません。 releaseを使用して、コストム・デリターunique_pointerのうち、非服装デレター・ユニーク・ポインターをプログラマーが構築していることを躊躇なく想像することができます。移動セマンティクスでは、プログラムはコンパイルに失敗します。

3

あなたがしていることは危険です。 getTree()を呼び出したら、もう一度呼び出すことはできません。これはインターフェイスからはわかりません。デザインを再考することもできます(shared_ptrはより良い仕事をするかもしれません。単純にルートを生のポインタとして保存し、手作業でその割り当てを処理します)。

とにかく、あなたの意図をより明確にするために、あなたのデザインを固執したい場合は、std::moveを使用する方が良い方法です。

EDIT:明らかに 'はいけません'は、英語での禁則の特別な意味を持っています。私は気づいていませんでした。関数を2回または何回でも呼び出すことはできますが、連続して実行されると有効なオブジェクトへのポインタは返されません。

+0

'getTree()'をもう一度呼び出すことは問題ありません。ヌル 'unique_ptr'を返します。 –

+1

なぜ 'getTree()'を2回も呼び出さないといけないのですか?ルートが移動されると、 'nullptr'に設定されます。したがって、それから再び移動すると' nullptr'が返されます。これは空のオブジェクトにとって非常に妥当な動作のようです。 – nwp

+0

なぜそれはあなたが2回呼び出さないことを提案しているのですか? – AngryDuck

関連する問題