无法在此基本Qt代码段中找到错误,但是我被告知肯定存在该错误?

问题描述 投票:0回答:2

我最近一直在尝试进入Qt,以更好地理解类层次结构和OOP。我只是在测试银行遇到这个问题,要求“修复”此代码以防止编译器和运行时错误。但是,很遗憾,我找不到解决方案,而且我自己也无法提出解决方案。对我来说,所有QObject派生的类都处理所有内存释放。因此,以下代码不会引起我看到的任何问题,并且可以编译。

#include <QLabel>
#include <QWidget>
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QLabel label("my string");
    QWidget window;
    label.setParent(&window);
    window.show();
    return a.exec();
}
c++ qt memory-management
2个回答
1
投票

对我来说,所有QObject派生的类都处理所有内存的重新分配。

正是这就是为什么此示例代码包含当您关闭window时会看到的那种错误。 Qt的父子系统以小部件管理其子寿命的方式工作,并在自身被删除时将其删除。

因此,当QApplication退出时,将调用~QWidget()析构函数,从而导致label的删除。因此,将调用~QLabel()

但是,另一方面,当main完成时,将删除局部变量,label是其中之一。它不是指针,而是值变量,我们再次调用~QLabel()

析构函数的两次调用是错误。可以通过通过label在堆上创建new来解决。


0
投票

Qt通过父子关系处理内存管理。如果父窗口小部件/窗口被销毁,它也将销毁所有子窗口/窗口。在这种情况下,标签设置为窗口的子级,这意味着Windows析构函数将尝试删除它。当它在堆栈上创建时,内存释放将失败。并且即使不这样做,main()的执行完成时,标签也会第二次被破坏,从而导致两次删除。正如其他人已经指出的那样,您可以通过使用QLabel *label = new QLabel("my string");在堆上分配标签来解决此问题,但是还有一个更简单的解决方案:重新排列窗口和标签的创建顺序:

© www.soinside.com 2019 - 2024. All rights reserved.