std::stack Objekt raus-moven

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Jonathan
Establishment
Beiträge: 2545
Registriert: 04.08.2004, 20:06
Kontaktdaten:

std::stack Objekt raus-moven

Beitrag von Jonathan »

Ich habe einen Stack der Objekte speichert, bislang mittels std::unique_ptr, weil ich mir keine Gedanken darüber machen wollte, wie ich meine Klasse movebar machen kann.
Jetzt muss ich allerdings ein Objekt aus dem Stack entfernen, damit aber noch weiter arbeiten können. stack::pop liefert aber kein Objekt zurück, und mit stack::top bekomme ich nur eine Referenz auf das oberste, d.h. ich müsste das Objekt kopieren, was mit einem unique_ptr ja nicht geht und was auch gar nicht passieren soll.
Wie bekomme ich jetzt ohne fiese Hacks mein Objekt aus dem Stack wieder raus?
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Florian Keßeler
Beiträge: 75
Registriert: 24.07.2002, 00:00
Wohnort: Bremen
Kontaktdaten:

Re: std::stack Objekt raus-moven

Beitrag von Florian Keßeler »

Spricht irgendetwas gegen

Code: Alles auswählen

auto top_element(std::move(stack.top())); stack.pop();
? Damit wird dein top zu einem leeren unique_ptr, der danach weggeräumt wird...
Benutzeravatar
Jonathan
Establishment
Beiträge: 2545
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: std::stack Objekt raus-moven

Beitrag von Jonathan »

Ja, das sieht schonmal gut aus. Aber nur mal so fürs Verständnis: Was genau passiert jetzt mit dem gemoveten Objekte? Ich meine, vor dem stack.pop muss da ja noch irgendein Objekt rumliegen, nur in einem ungültigen Zustand, weil es woanders hin gemoved wurde? Der unique_ptr muss das ja irgendwie wissen, weil er sonst bei stack::pop das Objekt trotzdem löschen würde? Aber es hat doch nicht jedes movebare Objekt einen "moved" Zustand?
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Schrompf
Moderator
Beiträge: 5047
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: std::stack Objekt raus-moven

Beitrag von Schrompf »

std::move() benutzt den Move-Konstruktor der Klasse. Und die Move-Operation wird halt so implementiert, dass das Quell-Objekt in einen eindeutigen Null-Zustand zurückgesetzt wird. Das braucht Dir keine Sorgen zu machen, das ist Aufgabe der Klasse. Und wenn die Klasse behauptet, movable zu sein, kannst Du Dich darauf verlassen.

Hier im Fall des std::unique_ptr wird der Instanzzeiger des Ptrs im Stack wahrscheinlich auf null gesetzt.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
dot
Establishment
Beiträge: 1745
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: std::stack Objekt raus-moven

Beitrag von dot »

Das unique_ptr move tut effektiv nichts andres als die Pointer der beiden beteiligten Objekte zu swappen. Im konkreten Fall wird also der Pointer aus dem Stack mit einem nullptr geswapped. Ergebnis davon ist, dass dein top_element nun den richtigen Pointer hat und der Pointer im Stack einen nullptr...
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: std::stack Objekt raus-moven

Beitrag von eXile »

Jonathan hat geschrieben:Ich meine, vor dem stack.pop muss da ja noch irgendein Objekt rumliegen, nur in einem ungültigen Zustand, weil es woanders hin gemoved wurde?
Das Original-Objekt wird durch den Move-Konstruktor in einen ungültigen Zustand versetzt. Den Move-Konstruktor musst du entsprechend so implementieren.
Jonathan hat geschrieben:Der unique_ptr muss das ja irgendwie wissen, weil er sonst bei stack::pop das Objekt trotzdem löschen würde?
Der Destruktor des Original-Objekts wird immer aufgerufen. Der Destruktor muss erkennen, dass this auf ein ungültigen Objekt zeigt; das musst du so entsprechend implementieren.
Jonathan hat geschrieben:Aber es hat doch nicht jedes movebare Objekt einen "moved" Zustand?
Die meisten gemoveten Objekte, welche tatsächlich Resourcen allokieren, haben so einen.

Als Standard-Beispiel siehe hier, wo _data == nullptr einen ungültigen Zustand anzeigt. Der Move-Konstruktor und Move-Assignment-Operator setzen diesen ungültigen Zustand beim Original-Objekt. Der Destruktor erkennt den ungültigen Zustand, und gibt keine Resourcen frei.
Florian Keßeler
Beiträge: 75
Registriert: 24.07.2002, 00:00
Wohnort: Bremen
Kontaktdaten:

Re: std::stack Objekt raus-moven

Beitrag von Florian Keßeler »

@dot: also zumindest in meiner libstdc++ ruft der Move-Konstruktor explizit release() des alten unique_ptrs auf und initialisiert den eigenen internen Zeiger mit dem Ergebnis. Swap wäre auch ein Extraschritt, weil der interne Zeiger des neu konstruierten Objekts erstmal mit nullptr initialisiert werden müsste.
Benutzeravatar
dot
Establishment
Beiträge: 1745
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: std::stack Objekt raus-moven

Beitrag von dot »

Ich sagte, dass das "effektive" Verhalten einem Swap entspricht; ich meinte damit nicht, dass jede Implementierung intern zwangsweie std::swap aufrufen muss... ;)
Benutzeravatar
Jonathan
Establishment
Beiträge: 2545
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: std::stack Objekt raus-moven

Beitrag von Jonathan »

Ich habe mich gerade eben mit dem Thema etwas weiter auseinandergesetzt und fand folgenden Artikel sehr hilfreich für das tiefere Verständnis:
http://www.cprogramming.com/c++11/rvalu ... c++11.html
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
dot
Establishment
Beiträge: 1745
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: std::stack Objekt raus-moven

Beitrag von dot »

Antworten