You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将成员控件设为QMainWindow中央控件为何未崩溃?

为什么将栈上的QGraphicsView设为QMainWindow中心部件后未出现双重删除崩溃?

代码示例

main.cpp

#include "main_window.hpp"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

main_window.hpp

#pragma once

#include "ui_main_window.h"

#include <QtWidgets/QMainWindow>
#include <QGraphicsView>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent)
    : QMainWindow(parent)
    {
        ui.setupUi(this);
        setCentralWidget(&view);
    }

private:
    Ui::MainWindowClass ui;
    QGraphicsView       view;
};

疑问来源

Qt文档中关于QMainWindow::setCentralWidget的说明:

注意:QMainWindow会接管控件指针的所有权,并在适当时机将其删除。

按照这个逻辑,程序结束时view应该被Qt所有权机制和MainWindow的析构函数双重删除,但实际却没有崩溃,这是为什么?


原因解析

  1. C++对象的析构顺序
    当MainWindow对象w在main函数结束时被销毁,析构流程是:

    • 先执行MainWindow的析构函数体(此处未自定义,故为空)
    • 按成员变量声明的逆序析构成员:先析构栈上的view对象,再析构ui
    • 最后调用基类QMainWindow的析构函数
  2. Qt对象树的自动维护机制
    QGraphicsView继承自QObject,当它被析构时,QObject的析构函数会自动将自身从父对象(即MainWindow)的子对象列表中移除。也就是说,在MainWindow的基类析构函数执行前,view已经被销毁,并且不再属于MainWindow的子对象集合。

  3. 避免双重删除的关键
    QMainWindow的析构函数只会遍历当前子对象列表,删除其中的对象。由于view已经提前从子列表中移除,基类析构函数不会再尝试删除它,因此不会出现“栈对象被delete”的未定义行为,自然也就不会崩溃。


内容的提问来源于stack exchange,提问作者qloq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:22:38