Pop-Methode der verknüpften Liste mit unique_ptr
Ich betrachte die Implementierung einer einfach verknüpften Liste mit unique_ptronhttps://solarianprogrammer.com/2019/02/22/cpp-17-implementing-singly-linked-list-smart-pointers/. Meine Frage bezieht sich auf folgende Methode:
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 };
Ich frage mich, warum das Provisorium hier benötigt wird? Warum konnten Sie nicht einfach tun head = std::move(head->next)? Liegt das daran, dass es zu einem Speicherleck führt? Gibt headbei einer Neuzuweisung unique_ptrautomatisch den aktuellen Speicher frei, auf den er zeigt?
Ich hatte den Eindruck, dass Smart Pointer narrensicher vor Speicherlecks sind. Es scheint in diesem Fall ein Speicherleck für das Original headzu geben, weil kein intelligenter Zeiger mehr darauf zeigt?
Antworten
Ich frage mich, warum das Provisorium hier benötigt wird?
Es wird nicht wirklich benötigt , aber es ist auch nicht schlecht zu bedienen.
Warum konnten Sie nicht einfach tun
head = std::move(head->next)? Liegt das daran, dass es zu einem Speicherleck führt?
Sie können. In diesem Beispiel wird es kein Leck geben.
Gibt
headbei einer Neuzuweisungunique_ptrautomatisch den aktuellen Speicher frei, auf den er zeigt?
Ja. Der alte Zeiger wird jedoch deleteerst nach der Übertragung des Besitzes des neuen Zeigers übertragen. Per CPReferenz:
https://en.cppreference.com/w/cpp/memory/unique_ptr/operator%3D
Überträgt das Eigentum von
ran,*thisals ob durch einen Aufrufreset(r.release())gefolgt von einer Zuweisung vonget_deleter()fromstd::forward<E>(r.get_deleter()).
https://en.cppreference.com/w/cpp/memory/unique_ptr/reset
Ersetzt das verwaltete Objekt.
Gegeben
current_ptrführt der von verwaltete Zeiger*thisdie folgenden Aktionen in dieser Reihenfolge aus:
- Speichert eine Kopie des aktuellen Zeigers
old_ptr = current_ptr- Überschreibt den aktuellen Zeiger mit dem Argument
current_ptr = ptr- Wenn der alte Zeiger nicht leer war, wird das zuvor verwaltete Objekt gelöscht
if(old_ptr) get_deleter()(old_ptr).
So:
In dem Fall, in dem tempverwendet wird, wird der Zeiger auf den alten Knoten in headzuerst tempüber seinen Bewegungskonstruktor verschoben und zurückgesetzt head, um ein zu halten nullptr. Dann wird dieser Zeiger head.operator=aufgerufen und abgerufen. next.release()Und dann tempwird der Gültigkeitsbereich deleteverlassen und der alte Knoten wird aktiviert.
Falls tempnicht verwendet wird, head.operator=wird aufgerufen next.release(), der alte Zeiger gespeichert und durch den freigegebenen Zeiger und dann deletedurch den gespeicherten Zeiger ersetzt.
So oder so kein Leck.
Ich hatte den Eindruck, dass Smart Pointer narrensicher vor Speicherlecks sind.
Bei richtiger Anwendung ja.
Es scheint in diesem Fall ein Speicherleck für das Original
headzu geben, weil kein intelligenter Zeiger mehr darauf zeigt?
Es gibt kein Leck, da immer unique_ptrauf den alten Knoten verwiesen wird, bis er pop()austritt und tempzerstört wird delete, wodurch der alte Knoten damit verbunden wird. Auch wenn tempweggelassen wird, wird der alte Knoten immer noch ordnungsgemäß zerstört, nachdem der Besitz seines nextZeigers übertragen wurde.