unique_ptrを使用したリンクリストのポップメソッド

Aug 20 2020

私はを使用unique_ptrして単一リンクリストの実装を見ていますhttps://solarianprogrammer.com/2019/02/22/cpp-17-implementing-singly-linked-list-smart-pointers/。私の質問は次の方法に関するものです。

 3 struct List {
 4     List() : head{nullptr} {};
 5 
 6     // ...
 7 
 8     void pop() {
 9         if(head == nullptr) {
10             return;
11         }
12 
13         std::unique_ptr<Node> temp = std::move(head);
14         head = std::move(temp->next);
15     }
16 
17     // ...
18 };

なぜここで一時的なものが必要なのか疑問に思いますか?なぜあなたは単にすることができなかったのですhead = std::move(head->next)か?これは、メモリリークが発生するためですか?ときにhead再割り当てされ、んunique_ptr、自動的にそれがポイントの現在のメモリを解放?

私は、スマートポインタがメモリリークからの確実な証拠であるという印象を受けました。この場合、オリジナルをhead指すスマートポインタがなくなるため、オリジナルのメモリリークが発生する可能性がありますか?

回答

4 RemyLebeau Aug 20 2020 at 07:36

なぜここで一時的なものが必要なのか疑問に思いますか?

本当に必要というわけではありません、使うのも悪くありません。

なぜあなたは単にすることができなかったのですhead = std::move(head->next)か?これは、メモリリークが発生するためですか?

あなたはできる。この例ではリークはありません。

ときにhead再割り当てされ、んunique_ptr、自動的にそれがポイントの現在のメモリを解放?

はい。ただし、delete新しいポインタの所有権が最初に譲渡されるまで、古いポインタは'dされません。cppreferenceごと:

https://en.cppreference.com/w/cpp/memory/unique_ptr/operator%3D

を呼び出した後、fromを割り当てることにより、所有権をからrに転送します。*thisreset(r.release())get_deleter()std::forward<E>(r.get_deleter())

https://en.cppreference.com/w/cpp/memory/unique_ptr/reset

管理対象オブジェクトを置き換えます。

  1. を指定するとcurrent_ptr、によって管理されていたポインタ*thisは、次のアクションをこの順序で実行します。

    1. 現在のポインタのコピーを保存します old_ptr = current_ptr
    2. 現在のポインタを引数で上書きします current_ptr = ptr
    3. 古いポインタが空でない場合は、以前に管理されていたオブジェクトを削除します
      if(old_ptr) get_deleter()(old_ptr)

そう:

tempが使用されている場合、の古いノードへのポインタは、head最初にtempそのmoveコンストラクタを介して移動され、headを保持するようにリセットされますnullptr。次に、そのポインタhead.operator=を呼び出しnext.release()て取得します。そして、tempスコープ外になり、delete'古いノードになります。

tempが使用されていない場合は、head.operator=を呼び出しnext.release()、古いポインタを保存して、解放されたポインタに置き換えてからdelete、保存されたポインタに置き換えます。

どちらの方法でも漏れはありません。

私は、スマートポインタがメモリリークからの確実な証拠であるという印象を受けました。

適切に使用すれば、はい。

この場合、オリジナルをhead指すスマートポインタがなくなるため、オリジナルのメモリリークが発生する可能性がありますか?

unique_ptr古いノードを参照しているので、pop()終了しtempて破棄されるまでリークはありませんdelete。 '古いノードを使用します。temp省略された場合でも、nextポインタの所有権が譲渡された後、古いノードは適切に破棄されます。