Muss man alle dynamisch erzeuge Distanzen wieder freigeben?
Muss man alle dynamisch erzeuge Distanzen wieder freigeben?
Hallo,
also ich hab grad mal eine für mich ziemlich wichtige Frage.
Ich hab mal an der Uni an nem Qt Kurs mitgemacht. Damals hat, soweit ich mich richtig erinnere, der Kursleiter gesagt, dass sich Qt teilweise selber um das "deleten" dynamischer erzeugter Speicherreservierungen kümmert.
Also ich bin mir aber überhaupt nicht mehr sicher ob ich das richtig in Erinnerung habe. Kann das sein? Und wenn ja, wann muss ich die Speicherreservierung eines z.B. QLabels wieder freigeben, wann muss ich mich daraum selber kümmern und wann nicht?
Bzw. ich hab schon versucht das irgendwo nachzulesen aber ich weiß nicht die genauen fachbegriffe deswegen kann ich nicht suchen....
Danke soweit...
mfg Cascoin
also ich hab grad mal eine für mich ziemlich wichtige Frage.
Ich hab mal an der Uni an nem Qt Kurs mitgemacht. Damals hat, soweit ich mich richtig erinnere, der Kursleiter gesagt, dass sich Qt teilweise selber um das "deleten" dynamischer erzeugter Speicherreservierungen kümmert.
Also ich bin mir aber überhaupt nicht mehr sicher ob ich das richtig in Erinnerung habe. Kann das sein? Und wenn ja, wann muss ich die Speicherreservierung eines z.B. QLabels wieder freigeben, wann muss ich mich daraum selber kümmern und wann nicht?
Bzw. ich hab schon versucht das irgendwo nachzulesen aber ich weiß nicht die genauen fachbegriffe deswegen kann ich nicht suchen....
Danke soweit...
mfg Cascoin
Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb
Wird ein QObject (oder eine davon abgeleitete Klassse) zerstört, greift der QObject-Destruktor und zerstört alle Kinder. Somit werden QObjects immer dann automatisch zerstört, wenn sie einen parent haben und dieser zerstört wurde. Als parents gelten auch parent-widgets oder layouts.QObject::~QObject () [virtual]
Destroys the object, deleting all its child objects.
Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb
Hi,
danke für die schnelle Antwort.
Ok, heißt das dann, dass wenn ich mir eine Instanz Fensterklasse erzeuge, und auf dieser Fensterklasse QLabels und QPushbuttons WLayouts drauf sind, dass diese alle selbst zerstört werden wenn ich die Fensteklasse zerstöre? Weil die erben ja eigenltlich alle von QWidget....
Wäre ja schon sehr praktisch weil ich mich dann um ziemlich wenig kümmern müßte....
Also ich programmiere recht viel mit Fenstern. Dann würds ja reichen wenn ich immer dann wenn ich das Fenster nicht mehr brauche dieses Fenster zerstöre und alles andere zerstört sich automatisch....
Oder denke ich da zu einfach?
mfg Cascoin
danke für die schnelle Antwort.
Ok, heißt das dann, dass wenn ich mir eine Instanz Fensterklasse erzeuge, und auf dieser Fensterklasse QLabels und QPushbuttons WLayouts drauf sind, dass diese alle selbst zerstört werden wenn ich die Fensteklasse zerstöre? Weil die erben ja eigenltlich alle von QWidget....
Wäre ja schon sehr praktisch weil ich mich dann um ziemlich wenig kümmern müßte....
Also ich programmiere recht viel mit Fenstern. Dann würds ja reichen wenn ich immer dann wenn ich das Fenster nicht mehr brauche dieses Fenster zerstöre und alles andere zerstört sich automatisch....
Oder denke ich da zu einfach?
mfg Cascoin
Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb
Fast. Du zerstörst nicht deine Fensterklasse, sondern eine Instanz deiner Fensterklasse (Objekt). Ansonsten korrekt. Normalerweise reicht es, in main() ein Hauptfenster auf dem Stack anzulegen, der Rest läuft dann ganz automatisch (außer du verwaltest selber irgendwelche dynamisch alloziierten Toplevel-Fenster - die müssen schon selber zerstört weden, haben aber eben auch kein parent).Cascoin hat geschrieben:Ok, heißt das dann, dass wenn ich mir eine Instanz Fensterklasse erzeuge, und auf dieser Fensterklasse QLabels und QPushbuttons WLayouts drauf sind, dass diese alle selbst zerstört werden wenn ich die Fensteklasse zerstöre?
Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb
Und es ist richtig, das Du dich damit "schwertust"Also ich bin mir aber überhaupt nicht mehr sicher ob ich das richtig in Erinnerung habe. Kann das sein?
Das Zeugs verhaelt sich quasi wie nen Garbage Collector. In Sachen Ressourcen-Verbrauch und Performance ist das natürlich die Hölle, aber bei ner GUI iss die absolute performance eh zweitrangig, von daher isses auch irgendwie ok.
Qt Programmieren iss eh fast wie Java programmieren, nur eben mit c++ Syntax ^^
Ciao ...
Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb
Auch wenn es gegen gewisse C++-Konventionen verstößt (wer erstellt, soll es auch zerstören), ist es nciht nur bequem, sondern auch irgendwo nötig, siehe z.B. QUiLoader. Wer sollte da einen Destruktor definieren, um alle Ui-Elemente korrekt zu zerstören? Das ui selber? Das müsste dann das erzeugte QWidget überleben. Der Loader? Der müsste das erzeugte QWidget überleben. Bleibt eigentlich nur noch das erzeugte Widget.
Aber eigentlich ist es wie mit jeder Baumstruktur: Es gibt Nodes, jede Node verwaltet die eigenen children. Man kann eigene Node erstellen (per Ableiten). Sollte sich jetzt die abgeleitete Node wirklich selber um die eigenen erzeugten children kümmern, wenn es schon eine allgemeine Infrastruktur zum Zerstören der children gibt?
Wg. Performance: Die Hierarchie hat erstmal GAR NICHTS mit Garbage-Collector zu tun. Im Prinzip wird das Zerstören der children auch nur verlagert, von ~MyQObject in ~QObject, welcher ja am Ende des Zerstörungsprozesses eh aufgerufen wird. Kostet keine Performance. Ein Garbage-Collector würde ja regelmäßig scannen, ob irgedwo unreferenziert Objekte rumliegen. Das ist hier NICHT nötig. Entweder hab ich children -> gut, zerstören. Um eventuelle zusätzliche Referenzen außerhalb der Struktur muss sich dann der Programmierer selber kümmern (gut, das IST doof, wenn man ein QObject hat, das einerseits ein parent hat, andererseits außerhalb gebraucht wird, aber irgendwann mit dem parent zerstört wird. Aber für SOLCHE QObjects sollte man sowieso keine (kurzlebigen) parents verwenden. Singleton mit qApp als parent wäre hier evtl. was.)
Aber eigentlich ist es wie mit jeder Baumstruktur: Es gibt Nodes, jede Node verwaltet die eigenen children. Man kann eigene Node erstellen (per Ableiten). Sollte sich jetzt die abgeleitete Node wirklich selber um die eigenen erzeugten children kümmern, wenn es schon eine allgemeine Infrastruktur zum Zerstören der children gibt?
Wg. Performance: Die Hierarchie hat erstmal GAR NICHTS mit Garbage-Collector zu tun. Im Prinzip wird das Zerstören der children auch nur verlagert, von ~MyQObject in ~QObject, welcher ja am Ende des Zerstörungsprozesses eh aufgerufen wird. Kostet keine Performance. Ein Garbage-Collector würde ja regelmäßig scannen, ob irgedwo unreferenziert Objekte rumliegen. Das ist hier NICHT nötig. Entweder hab ich children -> gut, zerstören. Um eventuelle zusätzliche Referenzen außerhalb der Struktur muss sich dann der Programmierer selber kümmern (gut, das IST doof, wenn man ein QObject hat, das einerseits ein parent hat, andererseits außerhalb gebraucht wird, aber irgendwann mit dem parent zerstört wird. Aber für SOLCHE QObjects sollte man sowieso keine (kurzlebigen) parents verwenden. Singleton mit qApp als parent wäre hier evtl. was.)
Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb
Nein, aber sie Verhaelt sich wie einer !Die Hierarchie hat erstmal GAR NICHTS mit Garbage-Collector zu tun
C++ like ist:
Du konstruierst ein Root object.
Du hängst Childs rein
Du zerstörst das root Object
in dem Moment wo der DTor vom root Object durch ist, sollten alle Childs auch ausm Speicher sein.
Bei QT isses nicht so.
Die Fragmente und ganze Objekte verschwinden irgendwann kurz nachher, wenn irgendwie die MsgLoop mal durch ist.
In GUI Umgebung isses trivial, zugegeben. Aber so nen verhalten waere fuer gewisse Algorythmen der TodKostet keine Performance.
Stell Dir mal vor, Du willst was "RestRekursives" und deine im Stack erzeugten Heap Verwaltungsobjekte geben den Speicher nicht bei der Destruktion frei ! Der arme Hauptspeicher
Am Ende hasst Du aber Recht. GUI kann per definition nicht so performant sein ... Von daher ist die Programmierung eh komplett anders.
Es gibt einige Ansätze, GUI Bibliotheken streng an C++ Richtlinien auszurichten, aber die scheitern an der Usability. Also zählt die bei der GUI mehr.
Nen grafisches Entwicklungs-System (RAPID) würde sicher auch gehen, nur waere es um Welten komplexer.
Auf der anderen Seite bleibt aber immer noch die Frage, ist C++ die richtige Sprache fuer GUI's ?
Waere nicht binaerkompatibilitat zu Programmiersprachen, die besser auf GUI's ausgereichtet sind, der bessere Weg ?
Beispielsweisse die GUI in C# und .Net und die Business Logik in richtigen c++ (nicht managed).
Ciao ...
Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb
Gut, wer QObject in seinen Algo zieht, ist selber schuld - vor allem wenn der Algo sensibel istIn GUI Umgebung isses trivial, zugegeben. Aber so nen verhalten waere fuer gewisse Algorythmen der Tod
Prinzipiell wird die Eventloop nur DANN angeworfen, wenn das QObject über deleteLater() zerstört wird. Direktes Löschen per delete (oder automatisch per Stack) zerstört das QObject samt children sofort! Einzige Performancebremse ist das "emit destroyed()" (aber auch nur bei DirectConnection)- wer aber eine komplexe Aufgabe im angeschlossenen SLOT ausführt, dem gehört es nicht anders ^^
Prinzipiell gilt hier (wie überall):
Wer die Doku nicht liest, den erschlägt schnell das Biest.
Das Biest heißt Qt, und die Doku ist schee...
(frei nach der Oberwisenhuber Mühlbauerblas'n ^^)
Beachte die Warnings und Verweise in ~QObject.
Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb
Da sagst Du was ...Gut, wer QObject in seinen Algo zieht, ist selber schuld - vor allem wenn der Algo sensibel ist
Ich krieg hier (Professionelles Umfeld, Programmierer, die 10 Jahre schon an dem Thema programmieren) hier Schnittstellen vorgesetzt, die in komplexen hirarchien auftreten(mehrstufig, Parent kann 1000ende childs haben ... der wiedrum 1000 .... ) und ich bekomm als Basis Klasse
Code: Alles auswählen
class IWasWeissIch:: public QObject
{
QObject
public:
/* viele anderen methoden */
void destroy() = 0;
const IWasWeissIch * getParent() const = 0;
signals:
aboutToDestroy();
};
Das Teil soll ueber ne Dll Schnittstelle gehen !
genauer, ich soll das in nem Plugin solche Hirarchien implementieren ....
Instanzen von den Objecten sollen auch nie geclont werden (das das destroy sinn machen wuerde).
Wie willst du da noch performant programmieren koennen ???
Ciao ...