请问以下问题的解释是什么?
栈或堆? 通常情况下,没有父对象的QObject应该被创建在栈上或定义为另一个类的子对象。有父对象的QObject不应该被创建在栈上,因为这样可能会意外地导致它被删除两次。所有在堆上创建的QObjects都应该有一个父对象,或者由另一个对象进行管理。
来源:LINK
很抱歉,我要downvote接受的答案。目前两个版本都是错误的,尤其是结论非常错误。
Qt使用父/子概念来管理内存等内容。当一个对象被设置为另一个对象的子级时,则
operator delete
)所有子级。 当然,这是递归进行的;deleteLater
即可实现此操作——任何删除都将使其取消父子关系。这使您可以通过重复使用operator new
进行动态分配来构建QObject
树,并且不必手动删除所有已分配的对象。只需给它们父级,您就只需要删除树的根节点。您也可以随时删除子项(即子树),并且这将做正确的事情™。
最终,您将没有任何泄漏和双重删除。
这就是为什么在构造函数中您会看到以下内容:
class MyWidget : public QWidget // a QObject subclass
{
Q_OBJECT
public:
MyWidget(QWidget *parent = nullptr);
// default destructor is fine!
private:
// raw pointers:
// we won't own these objects through these pointers.
// we just need them to access the pointees
QTimer *m_timer;
QPushButton *m_button;
};
void MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
// don't need to save the pointer to this child. because reasons
auto lineEdit = new QLineEdit(this);
auto validator = new QIntValidator(lineEdit); // a nephew
// but let's save the pointers to these children
m_timer = new QTimer(this);
m_button = new QPushButton(this);
// ...
}
默认析构函数会正确删除整个树,即使我们通过调用operator new
分配了子对象,并且甚至没有保存指向某些子对象的指针。
在某些情况下,允许(并且实际上是一个好主意)为在堆栈上分配的对象提供父对象。
典型的例子是QDialog
子类:
void MyWidget::showOptionsDialog()
{
// OptionsDialog is a QDialog subclass;
// create an instance as a child of "this" object
OptionsDialog d(this);
// exec the dialog (i.e. show it as a modal dialog)
conts auto result = d.exec();
if (result == QDialog::Accept) {
// apply the options
}
// d gets destroyed here
// => it will remove itself as a child of this
}
this
作为对话框的父级传递的目的是允许对话框居中于父部件,共享任务托盘条目并与其模态。这在QDialog
文档中有解释。另外,最终,d
只需要在该函数中存在,因此将其声明为自动变量(即分配在堆栈上)是一个好主意。QObject
。QObject
置于堆栈上,请考虑以下代码:QObject *parent = new QObject;
QObject child(parent);
delete parent;
parent
会试图调用operator delete
来删除child
,一个并非使用new
(而是在栈上)分配的对象。这是非法的(也很可能导致崩溃)。d.exec()
期间,我们设法删除了this
,也就是对话框的父对象,该怎么办?这可能是由于各种非常难以跟踪的原因导致的——例如,数据通过套接字到达,导致UI中的小部件发生变化,创建一些并销毁其他一些。最终,您将删除堆栈变量,从而导致崩溃(并且试图重现崩溃可能会非常困难)。