Управление памятью в Qt?

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

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

MyClass.h

class MyClass
{

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

MyClass.cpp

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

    MyOtherClass myOtherClass2;

    QString myString = "Hello";
}

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

Ответ 1

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

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

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

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

Если ваш MyClass не является дочерним элементом QObject, вам придется использовать простой способ С++ делать вещи.

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

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

Ответ 2

Я хотел бы продлить ответ Дебильского, указав, что концепция собственности очень важна в 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.

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

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

Ответ 3

Родитель (объект 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 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/