我试图通过对QWidget进行子类化并导出静态类实例来创建单例类。但是,尝试删除此类实例会导致崩溃。为什么?
#include <QWidget>
#include <QApplication>
using namespace std;
class MyWidget : public QWidget
{
public:
static MyWidget *get_instance(){ static MyWidget instance; return &instance; };
};
int main
(
int argc,
char **argv
)
{
QApplication app( argc, argv );
MyWidget *widget = MyWidget::get_instance();
QWidget *parent_widget = new QWidget;
widget->setParent( parent_widget );
delete parent_widget; //crashes
return app.exec();
}
运行上面的代码会产生以下错误消息。我没有包含bakctrace消息,该消息太长而无法在此帖子中显示。
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-jon'
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-jon'
*** Error in `/home/shouheng/tmp/build-exp_main-Desktop_Qt_5_10_0_GCC_64bit-Debug/exp_main': free(): invalid pointer: 0x00000000006030c0 ***
[删除父窗口小部件时,将在其所有子窗口上调用delete
,从而在您未使用new
创建的单例对象的指针上被调用,即未分配在堆上:
static MyWidget instance;
为了避免这种情况,只需un-parent这样的单例对象
widget->setParent(nullptr);
在调用parent_widget
上的删除之前。
Qt与父母的所有权转移/处理所有权。
所以当你这样做
widget->setParent( parent_widget );
[parent_widget
将删除其析构函数中的widget
(除非其父级之前已更改)。