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

相关推荐
Ulyanov5 分钟前
基于Impress.js的3D概念地图设计与实现
开发语言·前端·javascript·3d·ecmascript
A南方故人9 分钟前
一个用于实时检测 web 应用更新的 JavaScript 库
开发语言·前端·javascript
JosieBook10 分钟前
【WinForm】使用C# WinForm实现带有托盘图标功能的应用程序
开发语言·c#
阿kun要赚马内12 分钟前
Qt写群聊项目(一):服务器
服务器·数据库·qt
2301_7903009613 分钟前
C++与量子计算模拟
开发语言·c++·算法
青灯照颦微19 分钟前
【R】三种方式安装R包
开发语言·r语言
野生技术架构师26 分钟前
深度拆解JVM垃圾回收:可达性分析原理+全类型回收器执行机制
java·开发语言·jvm
缺点内向27 分钟前
在 C# 中为 Word 段落添加制表位:使用 Spire.Doc for .NET 实现高效排版
开发语言·c#·自动化·word·.net
中科院提名者29 分钟前
如何配置go环境并用vscode运行
开发语言·后端·golang
电饭叔33 分钟前
GUI by Python 6 一段 gui 代码分析
开发语言·python