Muss man alle dynamisch erzeuge Distanzen wieder freigeben?

Alles rund um die Programmierung mit Qt
Antworten
Cascoin
Beiträge: 20
Registriert: 28. September 2010 17:32

Muss man alle dynamisch erzeuge Distanzen wieder freigeben?

Beitrag von Cascoin »

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
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb

Beitrag von franzf »

QObject::~QObject () [virtual]
Destroys the object, deleting all its child objects.
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.
Cascoin
Beiträge: 20
Registriert: 28. September 2010 17:32

Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb

Beitrag von Cascoin »

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
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb

Beitrag von franzf »

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?
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).
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb

Beitrag von RHBaum »

Also ich bin mir aber überhaupt nicht mehr sicher ob ich das richtig in Erinnerung habe. Kann das sein?
Und es ist richtig, das Du dich damit "schwertust" :-) Aus usability-Gründen "verstoesst" die Qt hier gegen ein paar C++ Grundregeln.
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 ...
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb

Beitrag von franzf »

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.)
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb

Beitrag von RHBaum »

Die Hierarchie hat erstmal GAR NICHTS mit Garbage-Collector zu tun
Nein, aber sie Verhaelt sich wie einer !

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.
Kostet keine Performance.
In GUI Umgebung isses trivial, zugegeben. Aber so nen verhalten waere fuer gewisse Algorythmen der Tod
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 ...
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb

Beitrag von franzf »

In GUI Umgebung isses trivial, zugegeben. Aber so nen verhalten waere fuer gewisse Algorythmen der Tod
Gut, wer QObject in seinen Algo zieht, ist selber schuld - vor allem wenn der Algo sensibel ist :P
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.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: Muss man alle dynamisch erzeuge Distanzen wieder freigeb

Beitrag von RHBaum »

Gut, wer QObject in seinen Algo zieht, ist selber schuld - vor allem wenn der Algo sensibel ist
Da sagst Du was ...

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();
};
vorgesetzt !!!

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 ...
Antworten