Braucht jede Klasse einen Destructer?
-
Meine Frage: Braucht eigentlich jede Klasse einen Destructer? Ich rufe einige funktionen auf und als ich damals noch einen destructer hatte wure er auch mit aufgerufen was ich nicht mochte.
Wisst ihr wie ich das verhindere das der Destructer mit aufgerufen wird?Hier meine dateien:
main.cpp
int main(int argc, char* argv[]) { getServer().send("Hey"); }server.cpp
Server::Server() { Constructer } Server getServer() { Server cServer; return cServer; } void Server::send(std::string message) { LOG("AUFRUF DER FUNKTION send"); } Server::~Server() { LOG("MEIN DESTRUCTER WURDE AUFGERUFEN OBWOHL ICH NUR DIE FUNKTION LOG AUFRUFEN WOLLTE"); //LOG(); //Wurde in einer anderen klasse defeniert }server.h:
#pragma once class Server { public: void send(std::string message); }; extern Server getServer();
-
Sobald du ein Objekt erstellst, wird der Destruktor aufgerufen.
Das willst du nicht verhindern, so funktioniert C++ und das macht die Sprache so mächtig. Wenn du nicht willst, dass da Code ausgeführt wird: Schreib da keinen Code rein.
-
Redthoobe schrieb:
Meine Frage: Braucht eigentlich jede Klasse einen Destruktor?
Nein.
Nathan schrieb:
Sobald eine automatische Variable die eine Klasseninstanz ist ihren Gültigkeitsbereich verlässt, wird der Destruktor aufgerufen.
ftfy.
-
Redthoobe schrieb:
Wisst ihr wie ich das verhindere das der Destructer mit aufgerufen wird?
Du kannst das Objekt auf dem Heap (also per new) erstellen, aber nie löschen (sprich kein delete aufrufen). Die Nachteile werden dir aber gleich an den Kopf geworfen

Dann kannst du dir mal das Singleton Pattern anschauen.
Und, was eigentlich eien Implementierung des Singletons wäre, du kannst in deiner getServer Funktion den cServer statisch machen, dann lebt der länger und der Destruktor wird nicht sofort wieder aufgerufen.
-
Swordfish schrieb:
Nathan schrieb:
Sobald eine automatische Variable die eine Klasseninstanz ist ihren Gültigkeitsbereich verlässt, wird der Destruktor aufgerufen.
ftfy.
Ist nicht wahr für Klassen mit trivialem Destrukter. Und bei Arrays wird je nach dem auch elementweise der Destruktor aufgerufen.
Ich empfehle placement new:
char *data = reinterpret_cast<char*>(malloc(1000)); // einfach eine genügend grosse Zahl wählen Server *psanccServer = new (&data) Server; // Der Nachteil von der von Skym0sh0 vorgeschlagenen Variante ist, // dass der Heap langsam ist. Hier ist die Variable aber auf dem Stack und daher gibt es maximalen Speed. // psanccServer = pointer to stack-allocated non-const class Server
-
troll dich?
-
Mensch Leute! Ihr verwirrt den armen Fragesteller wahrscheinlich nur mit euren Spitzfindigkeiten. Das ist zwar
allesteilweise (das mit dem placement-new ist Bullshit und grob fahrlässig so etwas einem Anfänger zu erzählen!) richtig (und es ist wichtig, dass man das irgendwann auch mal alles versteht!), aber wahrscheinlich braucht er gerade nur eine einfache und klare Antwort:Nein, du kannst den Destruktor auch weglassen, dann erstellt der Compiler für dich hinter den Kulissen einen leeren Destruktor (wo kein Code drin steht)

Finnegan
2. Edit: Tickt ihr eigentlich noch ganz sauber hier? Wie wäre es stattdessen einfach mal die Frage auf einem Niveau zu beantworten, das der Frage gerecht wird und vielleicht in einem Postscriptum auf ein paar Feinheiten aufmerksam zu machen? So wie das hier gerade aussieht, kann man dem Fragesteller auch gleich ein Buch von Jürgen Wolf empfehlen - das angesichts dieses Threads wohl weniger Schaden anrichten dürfte

-
taxospiesso schrieb:
Swordfish schrieb:
Nathan schrieb:
Sobald eine automatische Variable die eine Klasseninstanz ist ihren Gültigkeitsbereich verlässt, wird der Destruktor aufgerufen.
ftfy.
Ist nicht wahr für Klassen mit trivialem Destrukter. Und bei Arrays wird je nach dem auch elementweise der Destruktor aufgerufen.
Ich empfehle placement new:
char *data = reinterpret_cast<char*>(malloc(1000)); // einfach eine genügend grosse Zahl wählen Server *psanccServer = new (&data) Server; // Der Nachteil von der von Skym0sh0 vorgeschlagenen Variante ist, // dass der Heap langsam ist. Hier ist die Variable aber auf dem Stack und daher gibt es maximalen Speed. // psanccServer = pointer to stack-allocated non-const class ServerHä?
Erstens, bei einer einmaligen Allokierung und Initialisierung ist die Laufzeit gewöhnlich egal, weils eben nur einmal passiert.
Zweitens, sagen,d ass der Heap zu langsam ist, aber dann malloc (was ja auch nur den heap anspricht) aufrufen ist etwas von Poppelmoral geprägt.
Und drittens wirft ein Placement-new Probleme auf, wenn du den Speicher von lokalen Variablen nutzt, was deiner AUssage nach, maximalen Speed gibt.
-
Redthoobe schrieb:
Meine Frage: Braucht eigentlich jede Klasse einen Destructer? Ich rufe einige funktionen auf und als ich damals noch einen destructer hatte wure er auch mit aufgerufen was ich nicht mochte.
Wisst ihr wie ich das verhindere das der Destructer mit aufgerufen wird?Jede Klasse hat einen Destruktor, wenn Du ihn nicht schreibst, schreibt der Compiler einen für Dich und in einigen Fällen macht der überhaupt nichts.
In Deinem Fall wird ein Destruktor aufgerufen, weil Du ein Objekt kopierst (getServer()). Wenn Du verhindern möchtest, dass der Destruktor aufgerufen wird, solltest Du keine Server per value herum reichen:
int main(int argc, char* argv[]) { Server s; s.send("Hey"); }mfg Torsten
-
Redthoobe schrieb:
Meine Frage: Braucht eigentlich jede Klasse einen Destructer? Ich rufe einige funktionen auf und als ich damals noch einen destructer hatte wure er auch mit aufgerufen was ich nicht mochte.
Wisst ihr wie ich das verhindere das der Destructer mit aufgerufen wird?Jede Klasse hat automatisch einen Destruktor (EDIT: Ausser wenn sie eben keinen hat. Siehe dahier /EDIT). Wenn du keinen schreibst, dann erzeugt der Compiler einen für dich.
Und er wird vom Compiler auch automatisch aufgerufen.Gegenfrage: Warum willst du dass der Destruktor nicht aufgerufen wird?
Es gibt nämlich ganz sicher eine Lösung dafür was du versuchst zu machen, nur ist die ganz sicher nicht den Destruktor nicht aufzurufen. (Bzw. möglicherweise doch, aber nur wenn du gleich gar kein Objekt erzeugst.)
-
Torsten Robitzki schrieb:
In Deinem Fall wird ein Destruktor aufgerufen, weil Du ein Objekt kopierst (getServer()). [...]
Nope. Da wird dank RVO nix kopiert.
-
hustbaer schrieb:
Redthoobe schrieb:
Meine Frage: Braucht eigentlich jede Klasse einen Destructer? Ich rufe einige funktionen auf und als ich damals noch einen destructer hatte wure er auch mit aufgerufen was ich nicht mochte.
Wisst ihr wie ich das verhindere das der Destructer mit aufgerufen wird?Jede Klasse hat automatisch einen Destruktor. Wenn du keinen schreibst, dann erzeugt der Compiler einen für dich.
Aber nur, wenn er auch gebraucht wird, um mal wieder zu den Spitzfindigkeiten zurück zu kehren
.
-
Swordfish schrieb:
Torsten Robitzki schrieb:
In Deinem Fall wird ein Destruktor aufgerufen, weil Du ein Objekt kopierst (getServer()). [...]
Nope. Da wird dank RVO nix kopiert.
Und war der Hinweis auf eine möglicherweise vom Compiler, optional durchgeführte Optimierung jetzt hilfreich für den OP?

-
Der Punkt ist, daß wegen der (Nicht-)Kopie nix zerstört wird, aber am ende der
main()totsicher.
-
Swordfish schrieb:
totsicher
SeppJ schrieb:
zurück zu kehren
Bitte etwas auf Rechtschreibung achten!
-
Torsten Robitzki schrieb:
Und war der Hinweis auf eine möglicherweise vom Compiler, optional durchgeführte Optimierung jetzt hilfreich für den OP?

Wie ich anfangs schon erwähnt habe. Dieser Thread ist in eine Katastrophe ausgeartet mit jeder Menge (teilweise sogar auch falschen) Informatioen, die für den Fragesteller zum jetztigen Zeitpunkt (die Frage lässt auf einen Einsteiger schließen) absolut unnötiger Ballast sind. Das kommt einem hier ein wenig so vor also ob sich hier die ganzen Experten wie die Geier auf eine Anfängerfrage stürzen und alle zeigen wollen dass sie den längsten ...
(... Absatz aus dem C++Standard auswendig aufsagen können)herb Sutter hat das mal (wenn auch in einem anderen Kontext) schön auf den Punkt gebracht:
"It's hard toberemember that you are an expert."Es reicht erstmal wirklich aus zu wissen, dass man keinen Destruktor schreiben muss und dass das dann dasselbe ist als hätte man einen Destruktor mit leerem Funktionskörper geschrieben (tu (quasi) nix!).
Finnegan
-
SeppJ schrieb:
hustbaer schrieb:
Redthoobe schrieb:
Meine Frage: Braucht eigentlich jede Klasse einen Destructer? Ich rufe einige funktionen auf und als ich damals noch einen destructer hatte wure er auch mit aufgerufen was ich nicht mochte.
Wisst ihr wie ich das verhindere das der Destructer mit aufgerufen wird?Jede Klasse hat automatisch einen Destruktor. Wenn du keinen schreibst, dann erzeugt der Compiler einen für dich.
Aber nur, wenn er auch gebraucht wird, um mal wieder zu den Spitzfindigkeiten zurück zu kehren
.Hmmmmmmm *nachdenk*.
OK, Mist!Also du meinst Klassen deren Dtor weder userdefiniert ist, noch irgendwo benötigt wird. OK, ja, die haben dann keinen. Und sie müssen nichtmal einen haben können wenn ich genauer drüber nachdenke. Sie könnten ja ne Basisklasse mit nem privaten Dtor haben -- dann würde der Compiler beim Versuch den impliziten Dtor zu generieren Zahnräder spucken.
Oder hast du was anderes gemeint?
-
hustbaer schrieb:
Also du meinst Klassen deren Dtor weder userdefiniert ist, noch irgendwo benötigt wird. OK, ja, die haben dann keinen. Und sie müssen nichtmal einen haben können wenn ich genauer drüber nachdenke. Sie könnten ja ne Basisklasse mit nem privaten Dtor haben -- dann würde der Compiler beim Versuch den impliziten Dtor zu generieren Zahnräder spucken.
Oder hast du was anderes gemeint?
Genau die 2 Fälle meinte ich. Und noch den 2.5ten Fall, dass man den Destruktor explizit deleted.
-
Ach... scheiss drauf. Wenn der Thread eh schon im Arsch is
...SeppJ schrieb:
Und noch den 2.5ten Fall, dass man den Destruktor explizit deleted.
... mach ich eigentlich immer so, seitdem hab ich kein Problem mehr mit Dangling Pointers! :p
struct Dindong { ~Dindong () = delete; }... habe sogar einen Smart Pointer dafür geschrieben,
immortal_ptr, der in seinem Destruktor explizit keindeletemacht, ist sicherer so, weil man es sonst vergisst und eventuell den Pointer deleted.
Es gibt sogar eine Utility-Funktionmake_immortal, die den Pointer auch dann nicht deleted, wenn eine Exception geworfen wird... sicher ist sicher
Finnegan
-
Finnegan schrieb:
SeppJ schrieb:
Und noch den 2.5ten Fall, dass man den Destruktor explizit deleted.
... mach ich eigentlich immer so, seitdem hab ich kein Problem mehr mit Dangling Pointers! :p
struct Dindong { ~Dindong () = delete; }Ich steh gerade auf dem Schlauch, in welchem Anwendungsfall sollte man einen DTOR deleten wollen?
-
Wüsste ich auch nicht, es sei denn man deleted den Default-Ctor gleich mit. Der Unterschied zu nem Namespace wäre dann immerhin noch dass man die Klasse z.B. als "Funktionssammlung" an ein Template übergeben könnte.
Dass das ein Scherz von Finnegan war ist die aber klar, oder?