你能把QWidgets放到栈上吗?

Can you put QWidgets on the stack?

背景故事:

我审查了我的一些代码,我制作了一个本地 QMessageBox 用于显示错误,并将其分配给堆:

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

开发者说:

This pointer will leak, you are setting no parent and you never delete it. Here as well you do not need a pointer. As for the parent do not use 0, but Core::ICore::mainWindow().

我很困惑,因为我认为:

  1. QWidgets 只在堆上工作
  2. 当消息框关闭时指针会自动delete error;

我试过把QMessageBox放到栈上,但是没有显示。


问题:

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

I tried putting the QMessageBox on the stack, but it did not show.

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

原则上可以在栈上创建QWidget对象。在这里,它不起作用,因为对 error->show() 的调用不会立即显示消息框,它只是安排在返回主偶数循环时显示,此时对象将被销毁。因此,deleteing QMessageBox 也不起作用。设置父级将对象销毁的责任交给父级,当父级本身被销毁时,这是一个好主意。

但是,如果我理解你想要做什么,你想在 return 之前等待用户点击确定按钮。如果是这样的话,你最好使用静态的QMessageBox函数,比如QMessageBox::warning

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

error->setAttribute(Qt::WA_DeleteOnClose);

这将在相应的window关闭时触发删除。

堆栈上的 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 on stack"- 它应该是有效的和官方的证明。但是这和 QDialog::exec 是堆栈上 QWidgets 的唯一用例。

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

3)关于父对象 0:当失去对具有父对象的指针的引用时,您是安全的。如果父项被删除,所有子项都会自动删除(还有那些,您可能已经忘记了)。所以对于长运行的应用程序,"memory leak"只是暂时的。 在 parent =0 的情况下,它不会在 C++ 意义上泄漏,这使得内存检查器无法检测到此类泄漏。使用一些 QObject 树遍历函数仍然可以访问该指针。