当前位置: 首页 > news >正文

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(无状态)

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

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

intvalue=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防止悬空引用:

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 +receiverthisreceiverthis) 管理receiver销毁时自动断开
有捕获 Lambda + 外部receiverreceiver管理如果receiver先销毁,可能导致悬空
捕获原始指针/引用需手动管理(如QPointer悬空引用风险

结论

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

总结

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

http://www.jsqmd.com/news/100787/

相关文章:

  • 【论文阅读笔记】多实例学习手段 Diverse Density(DD):在特征空间中寻找正概念的坐标
  • a5 4444444444
  • 【必藏】AI大模型全景分析:程序员小白入门全指南,读这篇就够了
  • 2025年南宁头部环氧酚醛厂家推荐,环氧玻璃钢/石墨烯涂料/无溶剂环氧涂料/环氧酚醛/环氧酚醛设计找哪家 - 品牌推荐师
  • 从瑞吉外卖到南风窗图书管理系统:期末作业轻量化改造实战(最后附效果对比图)
  • A6 PRE接口发布
  • MM440如何用模拟量作为频率给定
  • FastAPI+VUE3创建一个项目的步骤模板(三)
  • 现代软件工程 - 2025秋 - 期末总结
  • 基于SpringBoot的超能驾校线上学习管理系统的设计与实现(毕业设计项目源码+文档)
  • GeoServer 跨域问题解决方案
  • 失眠的代价与认知的重塑:通宵测完 Nano Banana Pro,我只想说——这TM是未来!
  • 什么是可信计算?基于可信计算的网络安全自适应防护关键技术及应用
  • Codebuddy使用CloudBase MCP辅助AI编码基于Spec工作流开发的坦克大战小游戏
  • 【编号645】全国省市县行政区划矢量数据2025年更新
  • Arbess从基础到实践(19) - 集成GitLab+sourcefare实现Java项目代码扫描通过后自动化部署
  • 基于SpringBoot的博物馆管理系统(毕业设计项目源码+文档)
  • Part 10|我给这套系统划的第一个边界
  • 量子计算突破:零级魔法态蒸馏显著降低开销与噪声
  • Arbess从基础到实践(16) - 集成GitHub实现Java项目构建并自动化Docker部署
  • JavaScript——js基础(详细 全面),适合新手小白,收藏这篇就够了
  • Part 11|模块划分并非越细越好,关键在于明确职责边界
  • 基于SpringBoot的车辆报废回收系统(毕业设计项目源码+文档)
  • Arbess从基础到实践(17) - 集成GitLab+SonarQube实现代码扫描完成后自动化部署
  • Arbess从基础到实践(18) - 集成GitPuk实现Java项目自动化构建并Docker部署
  • ASJ10-GQ自复式过欠压保护器,电网波动的“隐形防护盾”
  • 为什么过滤 rtmpt 而不是 rtmp?
  • 2025年优测压测平台与JMeter效率成本对比及行业实践
  • 日志打印配置:logback-spring.xml配置;info和error完全区分了,并且按时间拆分了
  • 基于微信小程序的跑腿系统的设计与实现毕业设计项目源码