Gestione della memoria in Qt?

Sono abbastanza nuovo a Qt e mi sto chiedendo alcune cose di base con la gestione della memoria e la vita degli oggetti. Quando devo cancellare e / o distruggere i miei oggetti? Qualcuno di questi è gestito automaticamente?

Nell’esempio seguente, quale degli oggetti che creo devo cancellare? Cosa succede alla variabile di istanza myOtherClass quando myClass viene distrutto? Cosa succede se non elimini (o distruggi) i miei oggetti? Sarà un problema per la memoria?

MyClass.h

 class MyClass { public: MyClass(); ~MyClass(); MyOtherClass *myOtherClass; }; 

MyClass.cpp

 MyClass::MyClass() { myOtherClass = new MyOtherClass(); MyOtherClass myOtherClass2; QString myString = "Hello"; } 

Come puoi vedere, questo è abbastanza newbie-roba facile ma dove posso imparare a riguardo in un modo semplice?

Se si crea la propria gerarchia con QObject , cioè, si inizializzano tutti i QObject appena creati con un genitore,

 QObject* parent = new QObject(); QObject* child = new QObject(parent); 

allora è sufficiente delete il parent , perché il distruttore del parent si prenderà cura di distruggere un child . (Lo fa emettendo segnali, quindi è sicuro anche quando si cancella manualmente un child prima del genitore.)

Puoi anche eliminare prima il bambino, l’ordine non ha importanza. Per un esempio in cui l’ordine conta, ecco la documentazione sugli alberi degli oggetti .

Se la tua MyClass non è figlia di QObject , dovrai usare il semplice modo C ++ di fare le cose.

Inoltre, si noti che la gerarchia padre-figlio di QObject è generalmente indipendente dalla gerarchia della gerarchia di classi C ++ / albero di ereditarietà. Ciò significa che un bambino assegnato non ha bisogno di essere una sottoclass diretta del suo genitore . Qualsiasi (sottoclass di) QObject sarà sufficiente.

Potrebbero tuttavia esserci alcuni vincoli imposti dai costruttori per altri motivi; come in QWidget(QWidget* parent=0) , dove il genitore deve essere un altro QWidget , a causa, ad esempio, dei flag di visibilità e perché in questo modo si QWidget un layout di base; ma per il sistema di gerarchia di Qt in generale, è consentito avere qualsiasi QObject come genitore.

Vorrei estendere la risposta di Debilski sottolineando che il concetto di proprietà è molto importante in Qt. Quando la class A assume la proprietà della class B, la class B viene cancellata quando la class A viene cancellata. Ci sono diverse situazioni in cui un object diventa proprietario di un altro, non solo quando si crea un object e si specifica il suo genitore.

Per esempio:

 QVBoxLayout* layout = new QVBoxLayout; QPushButton someButton = new QPushButton; // No owner specified. layout->addWidget(someButton); // someButton still has no owner. QWidget* widget = new QWidget; widget->setLayout(layout); // someButton is "re-parented". // widget now owns someButton. 

Un altro esempio:

 QMainWindow* window = new QMainWindow; QWidget* widget = new QWidget; //widget has no owner window->setCentralWidget(widget); //widget is now owned by window. 

Quindi, controlla spesso la documentazione, in genere specifica se un metodo influirà sulla proprietà di un object.

Come dichiarato da Debilski, queste regole si applicano SOLO agli oggetti che derivano da QObject. Se la tua class non deriva da QObject, dovrai gestire da solo la distruzione.

Il genitore (l’object QObject o la sua class derivata) ha un elenco di puntatori ai suoi figli (QObject / i suoi derivati). Il genitore cancellerà tutti gli oggetti nel suo elenco figlio mentre il genitore viene distrutto. È ansible utilizzare questa proprietà di QObject per rendere gli oggetti figlio da eliminare automaticamente quando il genitore viene eliminato. La relazione può essere stabilita usando il seguente codice

 QObject* parent = new QObject(); QObject* child = new QObject(parent); delete parent;//all the child objects will get deleted when parent is deleted, child object which are deleted before the parent object is removed from the parent's child list so those destructor will not get called once again. 

Ci sono altri modi per gestire la memoria in Qt, usando smartpointer. Il seguente articolo descrive vari puntatori intelligenti in Qt. https://blog.qt.digia.com/blog/2009/08/25/count-with-me-how-many-smart-pointer-classs-does-qt-have/

Per aggiungere a queste risposte, per la vérification, ti consiglio di utilizzare la libreria Visual Leak Detetor per i tuoi progetti Visual c ++, compresi i progetti Qt poiché basata su c ++, questa libreria è compatibile con le istruzioni new, delete, free and malloc , è ben documentato e facile da usare. Non dimenticare che quando crei la tua class di interfaccia ereditata QDialog o QWidget e quindi crei un nuovo object di questa class, non dimenticare di eseguire la funzione setAttribute(Qt::WA_DeleteOnClose) del tuo object.