我正在Windows上开发一个Qt桌面应用程序。在主窗口中,我需要在我的Tab Widget中添加一个小部件,它通常写在下面:
void MainWindow::setConfParas()
{
ConfParas *confparas=new ConfParas();
ui->TabWidget->addTab(confparas,"Configure Parameters");
}
我正在尝试将Singleton Pattern应用到我的ConfParas
类中,它设计得像这样
class ConfParas : public QWidget
{
Q_OBJECT
public:
static ConfParas* getInstance()
{
static ConfParas theConfParas;
return &theConfParas;
}
explicit ConfParas(QWidget *parent = 0);
ConfParas(const ConfParas&)=delete;
ConfParas& operator=(const ConfParas&)=delete;
//sth else...
}
以前的代码将写成:
void MainWindow::setConfParas()
{
ConfParas *confparas=ConfParas::getInstance();
ui->TabWidget->addTab(confparas,"Configure Parameters");
}
并且编译器没有发出任何错误消息,我可以轻松启动应用程序,但是当我关闭主窗口时, _CrtIsValidHeapPointer(阻止)错误被提出了! 所以我猜它发生在主窗口解构的时期。
答案 0 :(得分:1)
当您将指针传递给QObject
时,Qt将接管该指针的生命周期。它假设内存是动态分配的,然后在解除分配时调用delete
。此规则的一个例外是子项在其父项之前被销毁。
请参阅https://doc.qt.io/archives/4.6/objecttrees.html
您的静态成员在堆栈上声明,并由运行时管理。当您将其传递给QObject
时,您要求进行双重删除。也就是说,您致电QTabWidget::AddTab
,将所有权委托给QTabWidget
。这个QTabWidget
,一个非静态变量将在任何静态变量(你的QWidget
)之前被销毁。由于它是父项,因此它也会删除其子项(您的QWidget
),然后当main
结束时,它还会调用static QWidget
的析构函数,因此会进行双重删除。
如果你的静态成员是第一次调用时分配的指针,那么你就不会遇到这个问题。事实上,我知道一些开发人员会说这不是一个真正的问题(不是说我同意他们),因为在拆除建筑物之前清洁建筑物的重点是什么?