qt-lambda信号槽机制

想要调查,lambda信号槽在用完后会不会自己回收

写入成员变量

复制代码
private:  
    std::function<void()> lambdaSlot;  

初始化

复制代码
lambdaSlot = []() {
        qDebug() << "Lambda slot executed";
        // 可访问类成员(如this指针)
    };

cpp代码展示

复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);


    qDebug() << "Lambda slot executed1";
    std::function<void()> lambdaSlot1;
    lambdaSlot1 = []() {
            qDebug() << "Lambda slot executed 临时";
            // 可访问类成员(如this指针)
        };
    lambdaSlot2 = []() {
        qDebug() << "Lambda slot executed";
        // 可访问类成员(如this指针)
    };
    lambdaSlot = &lambdaSlot1;
    qDebug() << lambdaSlot;


    connect(ui->pushButton_2,&QPushButton::clicked,lambdaSlot1);
}


MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    (*lambdaSlot)();
//    lambdaSlot2();
}

lambda信号槽是独立的,即使使用std::function<void()> lambdaSlot1;生成对象在转为槽函数,也是不行的,因为,在传入的过程中生成了另一个对象

证明过程

现象,pushButton_2点击有效,pushButton点击直接死机

那么,QT C++lambda槽函数的生命周期,是否与信号发送对象绑定?

Qt C++ 中,lambda 槽函数的生命周期 不直接信号发送对象 绑定,而是取决于 lambda 本身的捕获方式接收对象(receiver)的生命周期

Lambda 槽函数的生命周期规则

(1) 无捕获的 Lambda(无状态)

cpp 复制代码
connect(sender, &Sender::signal, []() { 
    qDebug() << "No capture"; 
});
  • 生命周期:独立于任何对象,类似于普通函数。
  • 风险 :如果 sender 被销毁,连接会自动断开(Qt 默认行为),但 lambda 本身仍然有效(如果被其他地方引用)。

(2) 有捕获的 Lambda(有状态)

cpp 复制代码
int value = 42;
connect(sender, &Sender::signal, [value]() { 
    qDebug() << "Captured value:" << value; 
});
  • 生命周期
    • 如果 receiver(接收对象)是 this(当前对象)
      • Lambda 会被存储在 receiver 的内部数据结构中(如 QObjectPrivate)。
      • receiver 被销毁时,Qt 会自动断开所有相关连接,避免悬空引用。
    • 如果 receiver 是另一个对象
      • Lambda 的生命周期取决于该 receiver 对象的生命周期。
      • 如果 receiver 先被销毁,而 sender 仍然存在,可能会导致未定义行为(除非手动管理连接)。

(3) 使用 QPointershared_ptr 管理生命周期

如果 lambda 捕获了指针或引用,建议使用智能指针或 QPointer 防止悬空引用:

cpp 复制代码
QPointer<QObject> safeObj = someObj;
connect(sender, &Sender::signal, [safeObj]() {
    if (safeObj) {
        qDebug() << "Object still exists";
    }
});

信号发送对象(sender)的影响

  • 默认情况下 ,Qt 的信号槽连接是 AutoConnection (自动选择 DirectConnectionQueuedConnection)。
  • 如果 sender 被销毁
    • 所有由 sender 发出的连接都会被自动断开(Qt 内部管理)。
    • 但 lambda 本身可能仍然存在(如果被其他对象持有)。

关键结论

场景 生命周期管理 风险
无捕获 Lambda 独立于任何对象 无悬空风险
有捕获 Lambda + receiverthis receiverthis) 管理 receiver 销毁时自动断开
有捕获 Lambda + 外部 receiver receiver 管理 如果 receiver 先销毁,可能导致悬空
捕获原始指针/引用 需手动管理(如 QPointer 悬空引用风险

结论

  • Lambda 槽函数的生命周期 主要取决于 捕获的变量receiver 对象 ,而不是 信号发送对象
  • Qt 默认会管理 senderreceiver 之间的连接 ,但 有捕获的 lambda 仍需手动管理悬空引用
  • 最佳方式 :尽量使用 this 作为 receiver,或使用智能指针确保安全。

总结

所以,使用lambda槽函数,一定要确保是一次性的,不会循环创建的,否则,不保证是否会有内存泄漏!

相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript