我是否需要显式删除顶级窗口以避免Qt中的内存泄漏



在Qt中,在构造QObject时分配了一个父级。将父项设置为 0 将构造一个没有父项的对象。如果对象是小部件,它将成为顶级窗口。如果我在堆上创建顶级窗口,是否需要显式删除顶级窗口以避免内存泄漏?或者Qt会照顾它。如果是这样,Qt什么时候删除它?在关闭小部件或关闭应用程序时?

我的理解是,现有的两个答案都是错误的。

https://qt.gitorious.org/qt/qtbase/source/f02e1d6d8e0ee560667b445e8fa43bde85e31f41:src/widgets/kernel/qapplication.cpp#L770

销毁 QApplication 时,顶级小部件将全部删除。

的确,在顶级窗口关闭之前,QApplication 不会从事件循环返回,但这与问题无关。

只要您的QApplication被正确销毁(即在堆栈上创建或以其他方式删除),所有小部件都将被删除。

您不必删除顶级小部件,并且不这样做不会导致技术或其他方面的泄漏。

(顶级QObjects不是这种情况,只有QWidgets,由QApplication跟踪)

技术上

内存

泄漏是指运行代码无法访问对象但仍存储在内存中

简短的回答是否定的。问题是您可以随时随地使用

QWidgetList QApplication::topLevelWidgets();

即使堆上的顶级小部件没有父级,它们也与QApplication对象相关联。碰巧这个对象的生存期就是程序的生存期。因此,即使 QApplication 对象不删除顶级小部件,当他被删除时,您的进程也会终止。这意味着这些小部件将在不久之后被删除。

有泄漏,但它发生在您从main()返回的时间和您的进程变成僵尸的时间之间。这完全没问题。

不释放顶级小部件的最大缺点是使用内存分析器会出现误报。

对于 QWidget,您可以设置 Qt::WA_DeleteOnClose 属性,以便在关闭 QWidget 时调用其析构函数。这将反过来调用所有子小部件的析构函数,确保任何内存分析器都不会显示误报。

不,您必须自己处理顶级小部件。如果您创建具有 2 个或更多没有父窗口的小部件的应用程序,您可能会注意到,当您关闭主窗口时,其他窗口仍处于活动状态并保持运行,除非您在主小部件的closeEvent()中选择不同的行为。

如果您想关闭并删除所有其他顶部小部件,您可以在主小部件的closeEvent中执行此操作(hide()所有其他顶部窗口并使用deleteLater()或直接删除它们)

最新更新