Konstruktor und Destruktor
-
hiho,
den Destruktor musst du bei der dynamischen Speicherverwaltung (new/delete) indirekt aufrufen, mittels delete bzw. delete[] (bei Arrays) Operator.
Bei allem Anderen braucht dich das nicht zu interessieren,
weil, wie du schon gesagt hast, der Destruktor automatisch,
beim Verlassen des Güligkeitsbereiches, aufgerufen wird.
-
dest schrieb:
Ab wann muss man den denn Destruktor manuell Aufrufen ?
In der Regel garnicht.
-
dest schrieb:
Ab wann muss man den denn Destruktor manuell Aufrufen ?
Als Anfänger kannst du erstmal davon ausgehen: niemals.
Ich behaupte mal das mindestens 95% der C++Programmierer niemals in die Situation kommen, in dem sie ein Destruktor manuell aufgerufen müssen.
-
Dweb schrieb:
den Destruktor musst du bei der dynamischen Speicherverwaltung (new/delete) manuell aufrufen, mittels delete bzw. delete[] (bei Arrays) Operator.
Selbst da rufst du den Destruktor nicht selbst auf (sondern nur indirekt).
-
Habe mal ein Beispiel gemacht:
#include <iostream> class Foo { public: ~Foo() { std::cout << "Destruktor" << std::endl; } }; Foo f_global; int main() { { Foo f_lokal; } // <-- f_lokal wird zerstört (automatisch). Foo* p = new Foo; delete p; // Hier musst du den Destruktor nun indirekt über den delete Operator aufrufen. system("pause>nul"); return 0; } // <-- f_global wird zerstört (automatisch). /* Insgesamt wurde der Destruktor nun also 3x augerfuen. */
-
Dweb schrieb:
Habe mal ein Beispiel gemacht:
Und nochmal: Auch hier hast du den Destruktor NICHT manuell aufgerufen. Das delete ihn aufruft ist ein Implementierungsdetail.
// Das wäre ein manueller Aufruf: A a; a.~A(); // In der Regel niemals nötig
-
~a();Das ist kein expliziter Aufruf des Destruktors.
Ein solcher müsste so aussehena.~A();
-
camper schrieb:
~a();Das ist kein expliziter Aufruf des Destruktors.
Ein solcher müsste so aussehena.~A();Da merkt man schon wie selten man so etwas braucht

-
Egal wie selten ich es brauchen werde. ^^
Wenn man weiss wie es geht dann schadet es auch wohl nicht. ^^
Danke für die Hilfen.
-
dest schrieb:
Wenn man weiss wie es geht dann schadet es auch wohl nicht. ^^
Solange man nicht weiss, in welchen Situationen manuelle Destruktoraufrufe sinnvoll sind, nützt einem die Information auch nichts.

asc hat schon Recht. Du fährst besser damit, Destruktoren gar nie direkt aufzurufen.
-
Hi Nexus,
Nexus schrieb:
dest schrieb:
Wenn man weiss wie es geht dann schadet es auch wohl nicht. ^^
Solange man nicht weiss, in welchen Situationen manuelle Destruktoraufrufe sinnvoll sind, nützt einem die Information auch nichts.

asc hat schon Recht. Du fährst besser damit, Destruktoren gar nie direkt aufzurufen.
Dann lass uns mal an deinem Wissen teilhaben.
In welchen Situationen benutzt man denn manuelle Destruktor-Aufrufe?
Ich habe nämlich auch keine Ahnung
Ich rate mal: Vielleicht wenn man die Speicheranforderungen für new und delete neudefiniert?Gruß,
CSpille
-
CSpille schrieb:
Ich rate mal: Vielleicht wenn man die Speicheranforderungen für new und delete neudefiniert?
Ja. Solche Low Level Sachen.
Man könnte es bestimmt sonst auch noch für diverse schmutze Hacks benutzen.
-
dest schrieb:
Egal wie selten ich es brauchen werde. ^^
Wenn man weiss wie es geht dann schadet es auch wohl nicht. ^^
Doch kann es schaden.
Wenn du weisst wie, könntest du auf die Idee kommen es irgendwann zu verwenden. Wenn dir irgendwann aber das nötige Hintergrundwissen fehlt, um es richtig zu machen, machst du irgendwann Unsinn.
-
z.Bsp. immer beim zerstören, mit placement new`s erzeugter, objekte...
char* two_objects = operator new[sizeof(T)*2]; T* first = new(two_objects ) T(/*ctor-parameter*/); T* second = new(two_objects+sizeof(T)) T(/*ctor-parameter*/); /*iwas mit first und second machen*/ first ->~T(); second->~T(); operator delete[] two_objects;T ist natürlich als template-Parameter zu verstehen...
bb
-
sollte man mit placement new erzeugte objekte nicht auch mit placement delete wieder freigeben?
-
hustbaer schrieb:
placement delete
Was ist denn das?
-
LordJaxom schrieb:
Was ist denn das?
Zu jedem eigenen definiertem placemente new Operator sollte man auch ein placemente delete schreiben:
void* operator new(std::size_t size, Pool& pool) { return pool.alloc(size); } void operator delete(void* ptr, std::size_t size, Pool& pool) { pool.dalloc(ptr, size); }Der Grund ist der folgende:
class MyClass { public: MyClass() { throw std::exception("bum!"); } }; Pool pool; MyClass* myObject = new (pool) MyClass();Der Konstruktor wirft eine Exception. Damit der angeforderte Speicher vom placement new auch wieder sauber freigegeben wird, muss ein placement delete existieren.
Wenn man das Ding übrigens manuell aufrufen will, dann geht dies nur so:operator delete(myObject, pool);hustbaer schrieb:
sollte man mit placement new erzeugte objekte nicht auch mit placement delete wieder freigeben?
Man hat im placement
deleteOperator allerdings keine Typinformationen mehr, daher kann man keinen Destruktor mehr aufrufen. Dies muss irgendwie davor geschehen.Grüssli
-
hustbaer schrieb:
sollte man mit placement new erzeugte objekte nicht auch mit placement delete wieder freigeben?
Nein. Das placement new verwendet man meistens nur, um den Ctor explizit aufzurufen. Den Dtor ruft man explizit mit objekt.~Klassenname() auf.
Manchmal verwendet man das placement new auch, um einen Hint zu geben, zum Beispiel wer der später löschenden Thread wohl sein wird oder in der Nähe welchen anderen Speicherblocks man zu liegen kommen mag für mehr Lokalität. So ein Hint ist aber kein richtiger Piratenkodex, sondern mehr so eine Richtlinie. Und gehinteter Speicher mut mit normalem delete wieder freigegeben werden können.
Manchmal benutzt man placement new für memory pooling. Dann braucht man kein delete, weil der Witz ja ist, daß man, sobald die Antwort versichickt wurde, nachher den ganzen Pool wegschmeißt.
Statt pooling kann man's auch machen, um push_back zu beschleunigen-ersetzten ohne perfect forwarding. Leider ist bei Template-Pools der GCC dumm und kann kein placement delete. Aber mit c++0x ist der Druck nicht mehr da, sowas zu machen. Auch hier würde kein delete nötig sein, der z.B. vector das alles auch ohne delete gut managen kann.
Ich erinnere mich noch, daß ich dem delete auch Hints mitgeben wollte. Aber irgendwie ist da auch der Druck weg. Es gibt fettere Tricks um Speed zu machen. Und im besonderen Fall, daß man die Objektgröße haben muß, für den small object allocator, so kriegt man die zum Glück kostenlos oder zu geringeren Kosten als man es per Hand könnte.
-
Achja, es gibt ja keine Placement-Delete-Expression.
Den Operator manuell aufzurufen hat natürlich keinen Sinn, das führt einem den Destruktor ja nicht aus.
-
Das placement delete gibt es übrigens sehr wohl (siehe <new>) - es macht nur nichts:
inline void *__CRTDECL operator new(size_t, void *_Where) _THROW0() { // construct array with placement at _Where return (_Where); } inline void __CRTDECL operator delete(void *, void *) _THROW0() { // delete if placement new fails }(ausm msvc 9.0)
Falls das nicht vorhanden ist (aber man placement new nutzt), gibts auch mindestens ne warning - vll so gar nen error - weiß ich gar nicht mehr genau und bin auch zu faul... ^^
bb