你能把QWidgets放在堆栈上吗?

时间:2015-05-30 22:13:48

标签: c++ qt pointers qwidget qmessagebox

背景故事:

我检查了一些代码,并且我已经创建了一个本地QMessageBox来显示错误,并将其分配给堆:

if (getAutopilotList.error() == 0) {
    QMessageBox* error = new QMessageBox(0);
    error->setDetailedText(getAutopilotList.errorString());
    error->setText("something");
    error->setWindowTitle(tr("Error!"));
    error->show();
    return;
}

开发商说:

  

此指针将泄漏,您没有设置父项,您永远不会删除   它。在这里你也不需要指针。至于父母没有   使用0,但Core :: ICore :: mainWindow()。

我很困惑,因为我想:

  1. QWidgets仅适用于Heap
  2. 当消息框关闭时,指针会自动delete error;
  3. 我尝试将QMessageBox放在堆栈上,但它没有显示。

    问题:

    1. 我可以将这个QMessageBox放在堆栈上并让它工作,我应该吗?
    2. 我是否需要显式delete QMessageBox指针?
    3. 为什么在这种情况下将父级设置为0以上的重要内容?

3 个答案:

答案 0 :(得分:4)

  

我尝试将QMessageBox放在堆栈上,但它没有显示。

因为当线程超出范围时它会立即被销毁。您必须使用QMessageBox::exec()以块模式运行它。

答案 1 :(得分:4)

原则上,您可以在堆栈上创建QWidget对象。在这里,它不起作用,因为对error->show()的调用没有立即显示消息框,它只是在返回主偶数循环时调度显示,此时对象将被销毁。出于这个原因,delete QMessageBox也不会起作用。设置父对象会在父对象被销毁时将对象销毁的责任归于父对象,这是一个好主意。

但是,如果我了解您要执行的操作,则需要等待用户在return之前单击“确定”按钮。如果是这种情况,您最好使用静态QMessageBox功能,例如QMessageBox::warning

如果您想要一个持久性消息框,那么您的代码就可以了,但您应该添加以下调用:

error->setAttribute(Qt::WA_DeleteOnClose);

当相应的窗口关闭时,这将触发删除。

答案 2 :(得分:3)

堆栈上的QWidget工作,但对于大多数情况不实用,因为当保留范围时,删除堆栈上的对象。

看看任何(很多)Qt示例,你会发现模式:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);   
    MainWindow window; //inherits from QWidget, created on stack
    window.show();    
    return app.exec();
}

1)关于“堆栈上的QWidget”这个问题 - 它应该是证明,它是有效的和官方的。但是这次和QDialog :: exec再次是堆栈上QWidgets的唯一用例。

2)它不会伤害。如果您的编码规则要求为每个新调用删除 - 请执行此操作。否则,正确设置Qt :: WA_DeleteOnClose,并在关闭时删除它。

3)关于父0:当丢失对具有父项的指针的引用时,您是安全的。如果删除父项,则会自动删除所有子项(也可能已被遗忘)。因此对于长期运行的应用程序,“内存泄漏”只是暂时的。 使用parent = 0,它不会在c ++意义上泄漏,这使得内存检查器无法检测到此类泄漏。仍然可以使用一些QObject树遍历函数访问指针。