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槽函数,一定要确保是一次性的,不会循环创建的,否则,不保证是否会有内存泄漏!

相关推荐
SmoothSailingT4 小时前
C#——单例模式
开发语言·单例模式·c#
与遨游于天地4 小时前
接口与实现分离:从 SPI 到 OSGi、SOFAArk的模块化演进
开发语言·后端·架构
YouEmbedded4 小时前
解码Qt布局管理器与样式表
qt·样式表·布局管理器
醇氧4 小时前
Spring Boot 应用启动优化:自定义事件监听与优雅启动管理
java·开发语言·python
请叫我初学者4 小时前
Java学习心得、项目流程(一个Java实习3月的菜鸟)
java·开发语言·intellij-idea·java实习心得
代码游侠4 小时前
学习笔记——线程
linux·运维·开发语言·笔记·学习·算法
技术净胜4 小时前
MATLAB基本运算与运算符全解析
开发语言·matlab
企微自动化4 小时前
Java 实现 Token 安全缓存:使用 ReentrantLock 和单例模式实现并发安全的 Token 管理器
开发语言·javascript·ecmascript
古德new4 小时前
openFuyao容器平台:企业级云原生全生命周期管理实践指南
开发语言