Warum müssen wir den rvalue-Verweis auf null im Move-Konstruktor setzen?

8
%Vor%

Ich kann den Grund für das Festlegen von rhd.pds auf nullptr nicht verstehen.

Was passiert, wenn wir diese Zeile entfernen: rhs.pds = nullptr;

    
Omid 01.03.2014, 11:54
quelle

3 Antworten

12

Einige Details der Klasse wurden entfernt. Insbesondere weist der Konstruktor das DataStructure -Objekt dynamisch zu, und der Destruktor hebt es auf. Wenn Sie während einer Verschiebung den Zeiger von einem Widget auf einen anderen kopiert haben, hätten beide Widget s Zeiger auf dasselbe zugeordnete DataStructure -Objekt. Wenn diese Objekte dann zerstört werden, versuchen sie beide delete it. Dies würde zu undefiniertem Verhalten führen. Um dies zu vermeiden, wird für den Widget , von dem verschoben wird, der interne Zeiger auf nullptr gesetzt.

Dies ist ein Standardmuster bei der Implementierung eines Move-Konstruktors. Sie möchten das Eigentumsrecht für einige dynamisch zugewiesene Objekte von einem Objekt auf ein anderes übertragen. Sie müssen also sicherstellen, dass das ursprüngliche Objekt nicht mehr die zugeordneten Objekte besitzt.

Schematisch beginnen Sie mit dieser Situation, indem Sie den Besitz von DataStructure von einem Widget auf den anderen übertragen möchten:

%Vor%

Wenn Sie den Zeiger einfach kopiert haben, müssten Sie:

%Vor%

Wenn Sie dann den ursprünglichen Widget Zeiger auf nullptr setzen, haben Sie:

%Vor%

Der Besitz wurde erfolgreich übertragen, und beide Widget s können zerstört werden, ohne ein undefiniertes Verhalten zu verursachen.

    
Joseph Mansfield 01.03.2014, 11:58
quelle
2

Das DataStructure -Objekt ist wahrscheinlich "Eigentum" von Widget und das Zurücksetzen des Zeigers verhindert, dass es versehentlich gelöscht wird, wenn Widget zerstört wird.

Alternativ ist es üblich, Objekte auf einen "leeren" oder "default" -Zustand zurückzusetzen, wenn sie verschoben werden, und das Zurücksetzen des Zeigers ist ein harmloser Weg, der Konvention zu folgen.

    
Potatoswatter 01.03.2014 11:57
quelle
1
%Vor%

Ich habe einen Destruktor in der obigen Klasse hinzugefügt.

%Vor%

Um zu veranschaulichen, was passieren würde, wenn Sie die Nullptr-Zuweisung entfernen, überprüfen Sie die obigen Methoden. Ein Widget a würde in einer Hilfsfunktion erstellt und dem Widget b zugewiesen werden.

Da das Widget a den Geltungsbereich verlässt, wird sein Destruktor aufgerufen, der den Speicher freigibt, und Sie bleiben mit dem Widget b zurück, das auf die ungültige Speicheradresse verweist.

Wenn Sie rhs Nullptr zuweisen, wird auch ein Destruktor aufgerufen, aber seit     lösche nullptr tut nichts ist alles gut:)

    
Blaz Bratanic 01.03.2014 12:11
quelle