Aufruf Destruktor und dann der Konstruktor (zurücksetzen ein Objekt)
Ich zurücksetzen möchten ein Objekt. Kann ich es in der folgenden Art und Weise?
anObject->~AnObject();
anObject = new(anObject) AnObject();
//edit: this is not allowed: anObject->AnObject();
Dieser code ist offensichtlich eine Teilmenge der typische Lebenszyklus eines Objekts zugewiesen, durch die Platzierung neuer:
AnObject* anObject = malloc(sizeof(AnObject));
anObject = new (anObject) AnObject(); //My step 2.
//...
anObject->~AnObject(); //My step 1.
free(anObject)
//EDIT: The fact I used malloc instead of new doesn't carry any meaning
Die einzige Sache, die geändert wird, ist die Reihenfolge der Konstruktor-und Destruktor-Aufrufe.
So, warum in der folgende FAQ
alle, die bedrohlich erscheinen?
[11.9] Aber kann ich explizit aufrufen, ein
Destruktor, wenn ich mein Objekt zugeordnet
mit neuen?FAQ: kann Man nicht, es sei denn, das Objekt wurde
zugeordnet mit placement-new. Objekte
erstellt durch neue gelöscht werden müssen, die
zwei Dinge tut (an Sie erinnern): Anrufe
der Destruktor, dann befreit den Speicher.FQA: Übersetzung: löschen ist ein Weg, um
ausdrücklich rufen Sie einen Destruktor, aber es
auch plant den Speicher. Sie können
auch ein Destruktor ohne
freigeben von Speicher. Es ist hässlich und
nutzlos in den meisten Fällen, aber Sie tun können
.
Destruktor/Konstruktor-Aufruf ist offensichtlich normalen C++ - code. Garantien im code verwendet direkt das Ergebnis aus der Platzierung der neuen Garantien. Es ist der Kern des standard -, es ist rock solid Sache. Wie kann es sein, genannt "dirty" und präsentiert als etwas unzuverlässig?
Glaubst du, es ist möglich, dass die in der Platzierung und nicht-in-placement-Umsetzung der neuen sind anders? Ich denke über einige Kranken die Möglichkeit, dass regelmäßig neue kann z.B. die Größe der Speicherblock vor dem block, welche Platzierung neuen natürlich nicht tun würde (da es nicht keinen Speicher zuweisen). Dies könnte dazu führen, eine Lücke für einige Probleme... Ist wie neu() Umsetzung möglich?
Ich möchte überprüfen, dass ich nichts verpasse, wie der Letzte edit in der Frage.
InformationsquelleAutor | 2009-07-14
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nicht bekommen, angesaugt durch die FQA troll. Wie gewohnt, bekommt er die Fakten falsch.
Können Sie sicher rufen Sie den Destruktor direkt, für alle Objekte, ob Sie erstellt werden, mit der Platzierung von neuen oder nicht. Hässlich liegt im Auge des Betrachters, es ist in der Tat nur selten benötigt, aber nur harte Tatsache ist, dass sowohl Speicher-Allokation und-Objekt erstellen muss ausgewogen sein.
"Regulären" new/delete vereinfacht dies ein wenig durch das binden Zuweisung von Speicher-und Objekt-Erstellung zusammen und stack-Allokation vereinfacht es sogar noch weiter, indem Sie die beiden für Sie.
Jedoch, das folgende ist völlig legal:
Beide Objekte sind zerstört, und der stack-Speicher wird automatisch wieder zurückgeführt. doch im Gegensatz zu den FQA behauptet, der erste Aufruf des destruktors ist nicht vorausgegangen ist, durch die Platzierung neuer.
Glaubst du, es ist möglich, dass die in der Platzierung und nicht-in-placement-Umsetzung von neuen unterscheiden kann? Ich denke über einige Kranken die Möglichkeit, dass regelmäßig neue kann z.B. die Größe der Speicherblock vor dem block, und Platzierung neuer natürlich nicht (weil es nicht keinen Speicher zuweisen). Dies könnte dazu führen, eine Lücke für einige Probleme...
Es spielt keine Rolle, wie Sie sich unterscheiden. Die Umsetzung muss sicherstellen, dass mein code oben funktioniert, denn das ist konform. Pixie dust ist erlaubt.
Warum
(&bar)->~CBar();
stattbar.~CBar();
?Beide sind legal und das gleiche tun, aber die Frage ursprünglich
->~
also ich kann das auch nicht ändern.InformationsquelleAutor MSalters
Warum nicht implementieren Sie eine Methode Clear (), das tut, was der code in den Körper der Destruktor? Der Destruktor dann nur ruft Clear() und rufen Sie Clear (), die direkt auf ein Objekt zu "resetten".
Weitere option, wenn Ihre Klasse unterstützt Belegung richtig:
Ich dieses Muster für das zurücksetzen von std::stack-Instanzen, wie die stack-Adapter funktioniert
keine klare Funktion.
Sie pflegen müssen, damit der Destruktor von "Richtigkeit" - ich behaupte das verschieben der Destruktor-code in die Methode Clear (), so dass der Destruktor enthält nur einen einzigen Aufruf von Clear(). Ich Schreibe fast alle meine eigenen code auf diese Weise, BTW.
Ist es nicht unmöglich zu realisieren "destruktiven" Methode Clear ()? Es müsste frei heap zugeordneten Mitglieder, wenn der Aufruf von Destruktor. Aber wenn als reset-Methode wie, es müsste nur klar, dass solche Mitglieder und lassen Sie nutzbar. Dies würde erfordern, zur Umsetzung der Methode Init() und rufen Sie es von Konstruktor. Reset-Methode nennen würde, Klar() und dann die Init(). Init-Methoden Aussehen wie nicht-RAII-code. Und was, wenn mehrere Konstruktoren werden benötigt? Dies kann die Dinge zu komplizieren.
Es hängt von der Klasse Semantik. Wenn Wiederaufbau der Klasse nach klaren teuer ist, dann mit meinem zweiten Vorschlag. Ich würde sagen, entweder ist wahrscheinlich weniger kompliziert, als über Unordnung mit expliziten Destruktor-Aufrufe und die Verwendung von placement-new.
InformationsquelleAutor
Technisch ist es schlechte Praxis, um Aufrufe von Konstruktoren oder Destruktoren explizit.
Dem delete-Schlüsselwort landet, ruft Sie, wenn Sie es verwenden. Gleiche gilt für neue mit-Konstruktoren.
Tut mir Leid aber das code macht mich wollen, reißen mir die Haare aus. Sie sollten es tun wie diese:
Weisen Sie eine neue Instanz eines Objekts
Löschen Sie eine Instanz eines Objekts
Dies NIE tun:
Wenn Sie müssen die "reset" - ein Objekt, erstellen Sie entweder eine Methode, die löscht die Instanz-Variablen innerhalb, oder, was ich empfehlen Sie tun, ist, Löschen Sie das Objekt an, und ordnen sich ein neues.
Das bedeutet gar nichts. Perl verfügt über sechs Möglichkeiten, um schreiben Sie eine for-Schleife. Nur weil Sie Dinge machen KÖNNEN, die in einer Sprache, weil Sie unterstützt werden, bedeutet, Sie sollten Sie verwenden. Teufel, ich könnte schreiben, alle meine code mit für Schalter Aussagen, weil der "Kern" der Sprache unterstützt. Macht es nicht eine gute Idee.
Warum verwenden Sie malloc, wenn Sie eindeutig nicht haben. Malloc ist eine C-Methode.
New und Delete sind deine Freunde in C++
"Zurücksetzen" ein Objekt
Dort gehen Sie. Dieser Weg erspart Ihnen unnötig reservieren und freigeben von Speicher in eine gefährliche Mode. Schreiben Sie Ihre Reset () - Methode, um den Wert zu löschen, alle Objekte innerhalb Ihrer Klasse.
Siehe meine Antwort für warum.
Die Reset () - Methode erfordert Wartung.
Wenn Sie schrieb alle Ihre code die Weise, die Sie vorschlagen, würde ich sagen, dass Ihre gesamte Codebasis benötigen würde, Wartung
Technisch, sollten Sie ändern Sie die zweite Zeile des "Tue das" Teil zu
delete anObject
weilfree()
aufrufen nicht DestruktorenInformationsquelleAutor Brock Woolf
Können Sie nicht an den Konstruktor in der angegebenen Weise durch Sie. Stattdessen, so können Sie mit dem placement-new (wie dein code auch zeigt):
Dieser code ist garantiert gut definiert, wenn der Speicherplatz noch verfügbar ist – so wie es sein sollte in Ihrem Fall.
(Habe ich gelöscht-Teil darüber, ob dies ist fraglich, code oder nicht – es ist gut definiert. Full stop.)
Durch die Art und Weise, Brock hat Recht: wie die Umsetzung der
delete
ist nicht fest – es ist nicht das gleiche wie der Aufruf der Destruktor, gefolgt vonfree
. Immer paar Anrufe vonnew
unddelete
, mischen Sie niemals eins mit dem anderen: das ist nicht definiert.&
? :o) im Ernst: vielen Dank; ich habe vergessen, dassanObject
war schon ein Zeiger.Kein problem. Ich von Ihnen positiv bewertet werden, wenn Sie es geändert.
Aber, wenn ich es brauche (da der Zeiger auf Objekt zurückgesetzt ist, halten Sie sehr lange Warteschlange, die ich nicht wollen, zu analysieren), dann gibt es offensichtlich kein problem, oder?
Nur um zu dieser Antwort: Der Grund, aus dem die Platzierung neuer vorhanden ist, weil Sie nicht mehr als einen Konstruktor direkt.
Also, was würde passieren, wenn die Platzierung der neuen ctor-Aufruf eine exception wirft? Der Speicher wird nicht freigegeben, aber das Objekt noch nicht gebaut, also können wir nicht aufrufen, löschen uns selbst.
InformationsquelleAutor Konrad Rudolph
Beachten Sie, dass Sie nicht
malloc
undfree
verwendet werden, aberoperator new
undoperator delete
. Auch, im Gegensatz zu deinem code, durch den Einsatz neuer, du bist garantiert exception-Sicherheit. Die fast gleichwertige code wäre der folgende.Den reset Sie haben vor gültig ist, aber nicht idiomatisch. Es ist schwer zu bekommen Recht, und als solche ist in der Regel verpönt und entmutigt.
InformationsquelleAutor avakar
Können Sie nicht, rufen Sie den Konstruktor so, aber es ist nichts falsch mit der Wiederverwendung der Speicher aufrufen und die Platzierung neuer, wie lange Sie nicht löschen oder frei (freigeben) der Speicher. Ich muss sagen, zurücksetzen ein Objekt wie dieses ist ein bisschen dürftig. Würde ich schreiben, ein Objekt explizit rückstellbar, oder schreiben Sie eine swap-Methode verwenden, um es zurückzusetzen.
E. g.
InformationsquelleAutor Logan Capaldo
Wenn Ihr Objekt sinnvolle Zuordnung der Semantik (und richtigen operator=), dann *anObject = AnObject() macht mehr Sinn und ist einfacher zu verstehen.
InformationsquelleAutor EFraim
Ja, was Sie tun, ist gültig die meisten der Zeit. [basic.Leben]p8 sagt:
Es ist also legal, wenn Sie nicht über eine
const
oder Referenz Mitglied.Wenn Sie nicht über diese Garantie, die Sie verwenden müssen
std::launder
oder verwenden Sie den zurückgegebenen Zeiger durch die Platzierung von neuen (wie Sie tun sowieso), wenn Sie möchten, verwenden Sie das neue Objekt:InformationsquelleAutor Rakete1111
Es ist weit besser, nur um so etwas wie eine Reset () - Methode auf Ihr Objekt eher als Spiel mit placement-new.
Sie nutzen die Platzierung der neuen Funktion, die vorgesehen ist, um zu bestimmen, wo ein Objekt zugeordnet ist. Dies ist normalerweise nur ein Problem, wenn die hardware hat eine "Besondere" Speicher, wie einem flash-chip. WENN Sie wollen, um einige Objekte in den flash-chip, können Sie diese Technik verwenden. Der Grund dafür, dass es Ihnen ermöglicht der explizite Aufruf des destruktors ist, dass SIE jetzt die Kontrolle über den Speicher, so dass der C++ compiler nicht wissen, wie man die Freigabe Teil des löschen.
Es ist nicht sparen Sie viel code entweder mit einem reset-Methode, die Sie haben, um die Mitglieder auf Ihre Startwerte. malloc() macht das nicht, so sind Sie gehen zu müssen, zu schreiben, dass code im Konstruktor sowieso. Machen Sie einfach eine Funktion, die stellt Ihre Mitglieder, um die Startwerte, rufen Sie Reset() aufrufen des Konstruktors und auch von anderswo, die Sie brauchen.
InformationsquelleAutor manovi
Warum nicht reset über die operator=()? Dies ist nicht umstritten und weitaus mehr lesbar.
InformationsquelleAutor David Feurle