Управление памятью в Qt? - PullRequest
90 голосов
/ 22 марта 2010

Я довольно новичок в Qt и меня интересуют некоторые базовые вещи, связанные с управлением памятью и жизнью объектов. Когда мне нужно удалять и / или уничтожать мои объекты? Все это обрабатывается автоматически?

В приведенном ниже примере, какие объекты, которые я создаю, мне нужно удалить? Что происходит с переменной экземпляра myOtherClass, когда myClass уничтожается? Что произойдет, если я вообще не удаляю (или уничтожаю) свои объекты? Будет ли это проблемой для памяти?

MyClass.h

class MyClass
{

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

MyClass.cpp

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

    MyOtherClass myOtherClass2;

    QString myString = "Hello";
}

Как видите, это довольно просто для новичков, но где я могу узнать об этом простым способом?

Ответы [ 4 ]

95 голосов
/ 22 марта 2010

Если вы строите свою собственную иерархию с QObject s, то есть вы инициализируете все вновь созданные QObject s с родителем,

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

, тогда достаточно delete the parent, потому что деструктор parent s позаботится об уничтожении child.(Он делает это путем выдачи сигналов, поэтому он безопасен даже тогда, когда вы вручную удаляете child перед родителем.)

Сначала вы также можете удалить дочерний элемент, порядок не имеет значения.Для примера, где порядок имеет значение , здесь документация о деревьях объектов .

Если ваш MyClass не является потомком QObject, выдолжны использовать простой способ выполнения C ++.

Также обратите внимание, что иерархия родитель-потомок QObject s, как правило, не зависит от иерархии дерева иерархии классов C ++ / дерева наследования.Это означает, что назначенный ребенок не должен быть прямым подклассом своего родителя .Любой (подкласс) QObject будет достаточным.

Однако конструкторы могут накладывать некоторые ограничения по другим причинам;например, в QWidget(QWidget* parent=0), где родительский элемент должен быть другим QWidget, например, из-за флагов видимости и из-за того, что таким образом вы сделали бы некоторую базовую разметку;но для системы иерархии Qt в целом вам разрешено иметь любой QObject в качестве родителя.

46 голосов
/ 22 марта 2010

Я хотел бы расширить ответ Дебилски, указав, что концепция владения очень важна в Qt. Когда класс A предполагает владение классом B, класс B удаляется, когда класс A удаляется. Существует несколько ситуаций, когда один объект становится владельцем другого, а не только при создании объекта и указании его родителя.

Например:

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.

Другой пример:

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

Итак, часто проверяйте документацию, обычно она указывает, повлияет ли метод на владение объектом.

Как заявил Дебилски, эти правила применяются ТОЛЬКО к объектам, производным от QObject. Если ваш класс не является производным от QObject, вам придется справиться с уничтожением самостоятельно.

7 голосов
/ 22 марта 2010

Родитель (либо объект QObject, либо его производный класс) имеет список указателей на его дочерние элементы (QObject / его производный). Родитель удалит все объекты в своем дочернем списке, пока родитель будет уничтожен. Вы можете использовать это свойство QObject для автоматического удаления дочерних объектов при каждом удалении родительского объекта. Отношение может быть установлено с использованием следующего кода

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.

Есть другой способ управления памятью в Qt, используя smartpointer. Следующая статья описывает различные умные указатели в Qt. https://blog.qt.digia.com/blog/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have/

0 голосов
/ 16 июня 2018

Чтобы добавить к этим ответам, для проверки я бы порекомендовал вам использовать библиотеку Visual Leak Detetor для ваших проектов Visual c ++, включая проекты Qt, поскольку она основана на c ++, эта библиотека совместима с операторами new, delete, free and malloc, она хорошо документированы и просты в использовании. Не забывайте, что когда вы создаете свой собственный класс интерфейса, унаследованный QDialog или QWidget, а затем создаете новый объект этого класса, не забудьте выполнить функцию setAttribute(Qt::WA_DeleteOnClose) вашего объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...