QScopedPointer与Qt父子层级配合:QWidget是否会被重复删除?
问题分析与解答
你的推测完全正确,这段代码会导致QWidget被两次删除,触发未定义行为(大概率引发程序崩溃),原因如下:
- Qt父子对象机制:Test是QObject子类,当Test对象被销毁时,会自动递归销毁所有以它为父对象的子对象。这里QWidget的构造函数传入了
this(Test实例),所以QWidget会被Qt的父子销毁逻辑处理一次。 - QScopedPointer的特性:作为智能指针,widgetPtr是Test的成员变量,当Test对象销毁时,widgetPtr会被析构,此时它会自动调用
delete销毁指向的QWidget。
两者叠加就导致同一个QWidget被delete两次,这是严重的内存错误。
你提到的在QWidget构造时传入nullptr作为父对象是可行的解决方案之一,这样Qt的父子销毁机制就不会管控这个QWidget的生命周期,完全由QScopedPointer负责销毁,避免重复删除。
另外还有一种方案:如果需要保留Qt父子对象的特性(比如QWidget自动归属到父对象的窗口层级),可以直接去掉QScopedPointer,让Qt的父子机制全权管理QWidget的销毁,无需手动用智能指针持有。
修正代码示例
方案1:取消父子关系,保留QScopedPointer
class Test : public QObject { Q_OBJECT public: explicit Test(QObject *parent = nullptr) : QObject(parent) { widgetPtr.reset(new QWidget(nullptr)); // 传入nullptr,解除父子绑定 } private: QScopedPointer<QWidget> widgetPtr; };
方案2:依赖Qt父子机制,移除QScopedPointer
class Test : public QObject { Q_OBJECT public: explicit Test(QObject *parent = nullptr) : QObject(parent) { new QWidget(this); // 由Qt自动处理销毁 } };
内容的提问来源于stack exchange,提问作者Infinity
相关产品推荐
相关产品推荐

