我对 Qt 很陌生,想知道一些关于内存管理和对象生命的基本知识。我什么时候需要删除和/或销毁我的对象?这些都是自动处理的吗?
在下面的示例中,我需要删除我创建的哪些对象?当 myClass
被销毁时,实例变量 myOtherClass
会发生什么?如果我根本不删除(或销毁)我的对象会发生什么?会不会是记忆的问题?
我的类.h
class MyClass
{
public:
MyClass();
~MyClass();
MyOtherClass *myOtherClass;
};
我的类.cpp
MyClass::MyClass() {
myOtherClass = new MyOtherClass();
MyOtherClass myOtherClass2;
QString myString = "Hello";
}
正如你所看到的,这是非常简单的新手,但是我在哪里可以轻松地了解这一点?
如果您使用 QObject
构建自己的层次结构,即使用父级初始化所有新创建的 QObject
,
QObject* parent = new QObject();
QObject* child = new QObject(parent);
那么 delete
parent
就足够了,因为 parent
的析构函数会负责销毁 child
。 (它通过发出信号来做到这一点,因此即使您在父级之前手动删除 child
也是安全的。)
您也可以先删除孩子,顺序无关紧要。例如,此处的顺序确实 很重要的是 the documentation about object trees。
如果您的 MyClass
不是 QObject
的子级,则必须使用普通的 C++ 做事方式。
此外,请注意 QObject
的父子层次结构通常独立于 C++ 类层次结构/继承树的层次结构。这意味着,分配的子类不需要是其父类的直接子类。 QObject
的任何(子类)都足够了。
但是,由于其他原因,构造函数可能会施加一些限制;例如在 QWidget(QWidget* parent=0)
中,父级必须是另一个 QWidget
,因为例如可见性标志,并且因为您会以这种方式进行一些基本布局;但是对于 Qt 的层次系统,一般来说,您可以将任何 QObject
作为父级。
我想通过指出所有权的概念在 Qt 中非常重要来扩展 Debilski 的回答。当 A 类承担 B 类的所有权时,当 A 类被删除时,B 类也被删除。在许多情况下,一个对象成为另一个对象的所有者,而不仅仅是在您创建对象并指定其父对象时。
例如:
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 派生的,则您必须自己处理破坏。
父级(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 中还有其他方法可以使用智能指针来管理内存。下面的文章描述了 Qt 中的各种智能指针。 https://www.qt.io/blog/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have
为了补充这些答案,为了验证,我建议您将 Visual Leak Detetor
库用于您的 Visual c++ 项目,包括 Qt 项目,因为它基于 c++,该库与 new, delete, free and malloc
语句兼容,它有很好的文档和便于使用。不要忘记,当你创建自己的QDialog
或QWidget
继承的接口类,然后创建这个类的新对象时,不要忘记执行你的对象的setAttribute(Qt::WA_DeleteOnClose)
函数。
不定期副业成功案例分享
(It does this by issuing signals, so it is safe even when you delete child manually before the parent.)
->这不是它安全的原因。在 Qt 4.7.4 中,QObject 子代被直接删除(通过delete
,参见 qobject.cpp,第 1955 行)。首先删除子对象是安全的原因是 QObject 告诉它的父对象在它被删除时忘记它。ClassB
继承自QObject
并且ClassC
继承自ClassB
,那么ClassC
只有在ClassB
的析构函数是虚拟的时才会被 Qt 的父子关系正确销毁。