Qt槽函数中动态分配的QFrame对象如何正确释放内存
现有代码设计的问题
你当前在析构函数中直接delete固定指针的写法存在明显缺陷,不合理,具体问题如下:
- 重复点击按钮会造成内存泄漏:如果用户多次点击同一个按钮,对应指针会被新new出来的对象地址覆盖,之前创建的QFrame没有任何指针引用,永远无法被释放,析构函数只会释放最后一次创建的对象。
- 未初始化指针会触发崩溃:如果用户从未点击过对应按钮,类成员指针如果没有提前初始化为空,析构时delete野指针会直接导致程序崩溃。
- 没有利用Qt原生的对象树内存管理机制,做了多余且容易出错的手动内存管理。
正确实现方案
Qt中所有QObject派生类(包括QFrame、QWidget等所有控件)都支持对象树内存管理:创建对象时传入父对象指针,父对象销毁时会自动递归销毁所有子对象,不需要手动在析构函数中释放。
根据你的业务场景可以选两种实现方式:
场景1:每个按钮对应一个固定QFrame,重复点击不新建、只做显示
这种场景只需要在首次点击时创建对象,绑定父对象,后续点击直接复用即可:
- 头文件中声明成员指针时直接初始化为空,避免野指针:
private: QFrame *frame = nullptr; QFrame *frame_2 = nullptr; Ui::Test *ui;
- 改造槽函数逻辑,创建对象时指定当前窗口为父对象:
void Test::on_pushButton_clicked() { // 未创建过才new,避免重复创建 if (!frame) { // 传入this作为父对象,挂入当前Test窗口的对象树 frame = new QFrame(this); } frame->show(); frame->raise(); // 置顶避免被其他窗口遮挡 } void Test::on_pushButton_2_clicked() { if (!frame_2) { frame_2 = new QFrame(this); } frame_2->show(); frame_2->raise(); }
- 析构函数中不需要手动delete frame和frame_2,对象树会自动释放,只保留delete ui即可:
Test::~Test() { delete ui; }
场景2:每次点击按钮都弹出新的独立QFrame窗口,不需要复用
这种场景不需要用固定类成员存储指针,创建时设置关闭自动销毁属性即可,完全不需要手动管理内存:
void Test::on_pushButton_clicked() { QFrame *newFrame = new QFrame(this); // 设置窗口关闭时自动销毁对象,不会残留内存 newFrame->setAttribute(Qt::WA_DeleteOnClose); newFrame->show(); } void Test::on_pushButton_2_clicked() { QFrame *newFrame = new QFrame(this); newFrame->setAttribute(Qt::WA_DeleteOnClose); newFrame->show(); }
注意:如果弹出的QFrame需要是独立顶层窗口,不想随父窗口一起销毁,可以把new时的父对象参数改成nullptr,只要保留Qt::WA_DeleteOnClose属性,用户关闭窗口时就会自动释放内存,不会泄漏。
内容的提问来源于stack exchange,提问作者in.yssh
相关产品推荐
相关产品推荐

