Wie funktioniert das Löschen auf Destruktor verhindert Zuordnung?

8

In dieser SO-Frage wird angegeben, dass dieses Konstrukt die Stapelzuweisung verhindert der Instanz.

%Vor%

Meine Frage ist, wie verhindert es Zuteilung? Ich verstehe, dass es nicht möglich ist, diese Instanz explizit oder implizit zu löschen. Aber ich denke, das würde zu Speicherverlust bzw. Laufzeitfehler führen.

Sind Compiler intelligent genug, um das Problem zu lösen und einen Compilerfehler zu erzeugen? Warum sollte man das auch brauchen?

    
jnovacho 17.09.2013, 10:45
quelle

6 Antworten

16

Der Destruktor einer Variablen mit automatischer Speicherdauer (d. h. eine lokale Variable) müsste ausgeführt werden, wenn die Lebensdauer der Variablen endet. Wenn kein zugreifbarer Destruktor vorhanden ist, verweigert der Compiler das Kompilieren des Codes, der eine solche Variable zuweist.

Grundsätzlich unterscheidet man zwischen "Stack Allocation" (übrigens eine ungenaue Wahl von Begriffen) und Free Store Allocation, dass bei Konstruktaufrufen Konstruktoren / Destruktoren immer paarweise vorkommen, während bei freier Speicherzuordnung ein Objekt ohne erstellt werden kann Zerstörte es jemals. Daher verhindert der Code durch die Verhinderung des Zugriffs auf den Destruktor die Zuweisung einer lokalen Variablen des Typs (wenn der Konstruktor ausgeführt wird, muss der Destruktor ebenfalls ausgeführt werden, es gibt jedoch keinen Destruktor, daher wird das Programm zurückgewiesen.)

    
Jon 17.09.2013, 10:47
quelle
14
  

Ich verstehe, dass es nicht möglich ist, diese Instanz explizit oder implizit zu löschen.

Darüber hinaus ist es nicht möglich, jede Instanz zu zerstören ; ob durch Löschen oder auf andere Weise.

Das Deklarieren einer automatischen Variable (oder "Stapelzuordnung", wenn Sie möchten) bewirkt nicht nur, dass die Instanz erstellt wird, wenn das Programm den Deklarationspunkt erreicht; Es bewirkt auch, dass es zerstört wird, wenn das Programm diesen Block verlässt. Mit einem gelöschten Destruktor kann das nicht gemacht werden, daher ist die Deklaration nicht erlaubt.

Dies verhindert auch, dass Sie eine statische oder Thread-lokale Variable deklarieren, da dies auch Code generiert, um die Variable zu zerstören, wenn das Programm oder der Thread endet.

Die einzige Möglichkeit, eines davon zu erstellen, ist mit new , und wenn du das einmal getan hast, kannst du es niemals zerstören. Dies verhindert jedoch nicht die Stapelzuordnung:

%Vor%
  

Auch warum sollte man das brauchen?

Meiner Meinung nach würden Sie nicht. Ein obligatorisches Speicherleck ist ein schrecklicher Weg, um sicherzustellen, dass ein Objekt niemals zur falschen Zeit zerstört wird. Verwenden Sie stattdessen Techniken wie RAII , um Objekte zu verwalten, die eine dynamische Lebensdauer benötigen, um sicherzustellen, dass sie immer einen gut definierten Eigentümer haben (oder geteilte Besitzer), die dafür verantwortlich sind, sie nach der Verwendung zu löschen. Die Smartpointer in der C ++ 11-Standardbibliothek sind ein guter Ausgangspunkt.

    
Mike Seymour 17.09.2013 11:07
quelle
5

Wenn Sie einen Destruktor als gelöscht markieren, ist es unmöglich, das Objekt zu zerstören. Es spielt keine Rolle, ob es auf dem Stapel oder auf dem Heap ist. Die gesamte Zerstörung eines Objekts (ob automatisch, wenn es außerhalb des Gültigkeitsbereichs liegt oder% delete ausführt) ruft den Destruktor auf. Und da es der Compiler ist, der den Aufruf des Destruktors behandelt, merkt er, ob er als gelöscht markiert wurde und einen Fehler ausgibt.

Es verbietet jedoch nicht die Erstellung von Objekten, aber da Non-Pointer-Instanzen am Ende des Bereichs dekonstruiert werden, in dem sie deklariert wurden, gibt der Compiler einen Fehler aus, der das Ablehnen verhindert Erstellung der Instanz Es ist immer noch möglich, Instanzen mit new dynamisch zuzuweisen, wobei der Vorbehalt besteht, dass sie nicht gelöscht werden können, was möglicherweise zu einem Speicherverlust führt.

    
Some programmer dude 17.09.2013 10:47
quelle
3

Wenn Sie versuchen, FS_Only auf dem Stapel zu deklarieren

%Vor%

Der Destruktor wird automatisch bei der schließenden Klammer aufgerufen, so dass Sie einen Kompilierungsfehler erhalten.
Natürlich können Sie auch nicht delete a new 'ed eins:

%Vor%     
doctorlove 17.09.2013 10:50
quelle
2

Ich habe zwei Antworten:

Von "Die C ++ Programmiersprache":

  

Sie können nicht eine lokale Variable haben, die nicht zerstört werden kann (§17.2.2) ...

In meinen eigenen Worten:

Denken Sie einmal darüber nach - eine Variable, die auf dem Stack erstellt wurde, soll am Ende des Bereichs gelöscht werden, in dem sie deklariert wurde.

Wenn Sie den impliziten Destruktor des Objekts nicht zulassen, teilen Sie dem Compiler im Grunde mit: "Sie sind nicht berechtigt, dieses Objekt am Ende des Bereichs zu löschen." Der Compiler möchte nicht das Risiko eingehen, etwas zu erschaffen, das nicht zerstört werden kann (und es ist richtig - was ist, wenn es groß ist und Megabyte Speicher verliert?), Also weigert es sich, es zu erstellen. Damit bleibt nur eine Option: Sie können sie im kostenlosen Store erstellen und manuell verwalten.

Jetzt liegt die Verantwortung bei dir. Beachten Sie jedoch, dass dies ein schlechter Code ist - die Objekte können nie delete d sein, auch nicht manuell. Erinnere dich - du delete d der Destruktor! Wie es in anderen Antworten richtig angemerkt wurde, ist dies ein erzwungenes Speicherleck und sollte vermieden werden.

    
Oleksiy 18.09.2013 00:32
quelle
0

Die einzige Möglichkeit, ein solches Objekt zuzuweisen, wäre die dynamische Zuweisung ohne De-Allocation (das Objekt wird entweder durchgesickert oder durch Zeiger für die Dauer des Programms aufgerufen.)

Jeder Versuch, eine statische Instanz zuzuweisen, führt zu einem Kompilierungsfehler, wenn das zugewiesene Objekt den Gültigkeitsbereich verlässt (da der Destruktorcode nicht aufgerufen werden kann).

    
utnapistim 17.09.2013 10:49
quelle

Tags und Links