2016-12-02 1 views
1

Sagen Sie Pokemon ist eine Klasse. Betrachte dieses Snippet:Was passiert mit "verlorenen" Stack-Objekten?

Pokemon Eve(4,3); //call to constructor, creating first object on the stack 
Eve=Pokemon(3,5); //call to constructor again, creating a second object on the stack 

Beide Objekte werden auf dem Stapel erstellt. Nachdem die zweite Zeile ausgeführt wurde, kann auf das erste Objekt (mit den Parametern 4,3) nicht mehr zugegriffen werden. Was passiert damit? In welchem ​​Jargon wird dieser Prozess beschrieben? Müllabfuhr?

Antwort

6

Ich glaube, du verstehst falsch, was passiert. Das ursprünglich als Eve erstellte Objekt ist nach der zweiten Zeile nicht "verloren". Tatsächlich ist es immer noch dasselbe Objekt (womit ich meine, dass es immer noch dieselbe Speicheradresse hat). Die zweite Zeile weist dem Objekt einen anderen Wert zu, indem es den Zuweisungsoperator für das Objekt Eve aufruft. Der Parameter, der an den Zuweisungsoperator übergeben wird, ist das temporäre Objekt, das von Pokemon(3,5) erstellt wurde.

Es ist das genannte temporäre Objekt - Pokemon(3,5), das nach der zweiten Zeile zerstört wird. Seine Zerstörung ist keine "Garbage Collection" oder gar eine Heap Deallocation, da es in erster Linie ein Stack-Objekt ist und somit kein solches benötigt.

Ich denke, Sie denken darüber in Bezug auf Java/C# oder ähnliche verwaltete Sprachen, die nur Objektreferenzen und keine direkten Objekte haben. In C++ mit dem obigen Code haben Sie direkt mit Objekten zu tun. Um zu sehen, etwas Gleichwertiges zu dem, was Sie im Kopf haben, bedenken Sie:

Pokemon* Eve = new Pokemon(4,3); 
Eve=new Pokemon(3,5); 

Hier sind wir Zeiger und den Heap, anstatt den Stack. In diesem Fall verliert die zweite Zeile das ursprüngliche Objekt tatsächlich, weil es sich um den neu zugewiesenen Zeiger handelt. Dies ist Art von ähnlich wie in Java/C# mit nur normaler Zuweisung passiert. Der Unterschied ist natürlich, dass C++ keinen Garbage Collector hat, also ist das ursprüngliche Objekt in dem oben genannten Sinne wirklich in dem Sinne verloren, dass es ein Speicherleck ist.

1

Die Objekte werden nicht auf dem Heap, sondern direkt auf dem Stapel erstellt, so dass kein Speicherplatz verloren geht (d. H. Kein zugewiesener Speicherplatz wird nicht erreichbar). Die Zuweisung verwendet einfach den durch die Initialisierung von zugewiesenen Speicher.

Bearbeitet: Sorgfältigere Formulierung um die "Überschreiben" -Konkurrenz.

+0

Ich würde nicht sagen, dass der zugewiesene Speicherplatz "einfach überschrieben" wird. Der C++ Zuweisungsoperator kann mehrere Dinge tun, bevor er etwas überschreibt. Abhängig von der Implementierung von 'operator =()'! Kann es überhaupt nichts überschreiben! –

+0

Das ist genau das, was mit der Standardimplementierung passiert, und das sollte wohl jeder vernünftige Override tun, soweit die Semantik der Zuweisung geht. Zugegeben, die Frage bietet eine ausgezeichnete Gelegenheit, einen eingehenden Kommentar zu speziellen Operatoren in C++ zu schreiben, aber ich bin sehr im Zweifel, dass das OP dies gefordert hat. – shinobi

+1

Ganz richtig, deshalb habe ich nicht runtergestimmt. Es kommt jedoch ganz darauf an, was in der Pokémon-Klasse des OPs passiert.Der offensichtlichste Grund, 'operator =()' zu überschreiben, besteht darin, tiefe Kopien von Zeigern zu machen, was nicht nur einfach den Klasseninhalt "überschreibt". Mein Kommentar war mehr, um darauf hinzuweisen, dass wir nicht notwendigerweise Annahmen über OPs "Pokemon" -Klasse machen und pauschale Aussagen machen können. –

3

Es heißt "der Zuweisungsoperator" oder "=".

Das zweite Objekt ist das temporäre Objekt, nicht das erste. Nach der Konstruktion wird der Zuweisungsoperator des ersten Objekts aufgerufen, um dem ersten Objekt den Wert des zweiten Objekts zuzuordnen.

Danach wird der Destruktor des zweiten Objekts aufgerufen, und das zweite Objekt wird zerstört. Wo geht es? Bis zum großen Eimer in den Himmel. Es ist weg.