使用unique_ptr的链表pop方法

Pop method of linked list using unique_ptr

我正在查看在 https://solarianprogrammer.com/2019/02/22/cpp-17-implementing-singly-linked-list-smart-pointers/ 上使用 unique_ptr 的单向链表的实现。我的问题与以下方法有关:

 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 可能存在内存泄漏,因为不再有指向它的智能指针?

I am wondering why the temporary is needed here?

并不是真的需要,但也不好使用。

Why couldn't you simply do head = std::move(head->next)? Is this because it will result in a memory leak?

可以。本例不会有泄漏。

When head is reassigned, does unique_ptr automatically free the current memory it's pointing to?

是的。但是,在首先转移新指针的所有权之前,旧指针不会 delete'。根据 cppreference:

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

Transfers ownership from r to *this as if by calling reset(r.release()) followed by an assignment of get_deleter() from std::forward<E>(r.get_deleter()).

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

Replaces the managed object.

  1. Given current_ptr, the pointer that was managed by *this, performs the following actions, in this order:

    1. Saves a copy of the current pointer old_ptr = current_ptr
    2. Overwrites the current pointer with the argument current_ptr = ptr
    3. If the old pointer was non-empty, deletes the previously managed object
      if(old_ptr) get_deleter()(old_ptr).

所以:

在使用temp的情况下,指向head中旧节点的指针将首先通过其移动构造函数移动到temp,重置head持有一个nullptr。然后 head.operator= 将调用 next.release() 并获取该指针。然后 temp 将超出范围,delete'ing 旧节点。

在没有使用temp的情况下,head.operator=会调用next.release(),保存它的旧指针并用释放的指针替换,然后delete保存的指针。

两边都没有泄漏。

I was under the impression that smart pointers are fool proof from memory leaks.

如果使用得当,是的。

It seems in this case there might be a memory leak for the original head because there would no longer be a smart pointer pointing to it?

没有泄漏,因为总是有一个 unique_ptr 引用旧节点,直到 pop() 退出并且 temp 被销毁,delete'ing旧节点。即使 temp 被省略,旧节点在其 next 指针的所有权转移后仍会被正确销毁。