web-dev-qa-db-fra.com

Gestion de la mémoire dans Qt?

Je suis assez nouveau sur Qt et je me pose des questions de base sur la gestion de la mémoire et la vie des objets. Quand dois-je supprimer et/ou détruire mes objets? Est-ce que tout cela est géré automatiquement?

Dans l'exemple ci-dessous, lequel des objets que je crée dois-je supprimer? Qu'advient-il de la variable d'instance myOtherClass lorsque myClass est détruite? Que se passe-t-il si je ne supprime pas (ou ne détruis pas) mes objets? Sera-ce un problème de mémoire?

MyClass.h

class MyClass
{

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

MyClass.cpp

MyClass::MyClass() {
    myOtherClass = new MyOtherClass();

    MyOtherClass myOtherClass2;

    QString myString = "Hello";
}

Comme vous pouvez le voir, ce sont des choses assez faciles pour les débutants, mais où puis-je en savoir plus facilement?

90
Martin

Si vous créez votre propre hiérarchie avec QObjects, c'est-à-dire que vous initialisez tous les QObjects nouvellement créés avec un parent,

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

alors il suffit de delete le parent, car le destructeur parents se chargera de détruire child. (Il le fait en émettant des signaux, il est donc sûr même lorsque vous supprimez child manuellement avant le parent.)

Vous pouvez également supprimer l'enfant d'abord, l'ordre n'a pas d'importance. Pour un exemple où l'ordre importe , voici la documentation sur les arbres d'objets .

Si votre MyClass n'est pas un enfant de QObject, vous devrez utiliser la manière simple C++ de faire les choses.

Notez également que la hiérarchie parent-enfant de QObjects est généralement indépendante de la hiérarchie de la hiérarchie/arborescence d'héritage de classe C++. Cela signifie que un enfant affecté n'a pas besoin d'être une sous-classe directe de son parent . N'importe quelle (sous-classe de) QObject suffira.

Cependant, des contraintes peuvent être imposées par les constructeurs pour d'autres raisons; comme dans QWidget(QWidget* parent=0), où le parent doit être un autre QWidget, en raison par exemple de indicateurs de visibilité et parce que vous feriez une mise en page de base de cette façon; mais pour le système de hiérarchie de Qt en général, vous êtes autorisé à avoir n'importe quel QObject comme parent.

95
Debilski

Je voudrais étendre la réponse de Debilski en soulignant que le concept de propriété est très important dans Qt. Lorsque la classe A assume la propriété de la classe B, la classe B est supprimée lorsque la classe A est supprimée. Il existe plusieurs situations où un objet devient le propriétaire d'un autre, pas seulement lorsque vous créez un objet et spécifiez son parent.

Par exemple:

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 autre exemple:

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

Donc, vérifiez souvent la documentation, elle spécifie généralement si une méthode affectera la propriété d'un objet.

Comme indiqué par Debilski, ces règles s'appliquent UNIQUEMENT aux objets qui dérivent de QObject. Si votre classe ne dérive pas de QObject, vous devrez gérer la destruction vous-même.

46
Austin

Le parent (soit l'objet QObject ou sa classe dérivée) a une liste de pointeurs vers ses enfants (QObject/son dérivé). Le parent supprimera tous les objets de sa liste d'enfants tandis que le parent est détruit. Vous pouvez utiliser cette propriété de QObject pour que les objets enfants soient supprimés automatiquement chaque fois que le parent est supprimé. La relation peut être établie à l'aide du code suivant

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.

Il existe d'autres moyens de gérer la mémoire dans Qt, à l'aide de smartpointer. L'article suivant décrit divers pointeurs intelligents dans Qt. https://blog.qt.digia.com/blog/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have/

7
yesraaj