Files
scuc-qt-course/docs/teaching/examples/pitfall_lambda_capture/README.md
T
张宗平 6d1895d696 教学示例补 5 个:3 个坑点复现 + QTableWidget + Day5 学员管理器参考实现
- pitfall_stack_widget / pitfall_lambda_capture / pitfall_double_connect:
  默认跑正确写法(离屏验证退出码 0),--crash / --dangle 开关课堂现场触发
  真实崩溃/悬空访问
- table_widget:QTableWidget 单元格事件最小示例(新安排 Day4「表格事件」)
- student_manager:Day5 综合案例参考实现,离屏自测覆盖 JSON round-trip
  与 QThread 后台导入闭环
- 均接入 examples/CMakeLists.txt 的 add_teaching_example,手工维护区不影响生成器
2026-07-05 12:49:20 +08:00

41 lines
2.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 坑点复现:lambda 槽的生命周期与 connect 第五参数 —— 教学补充示例
> 对应教案 [`OUTLINE_4DAY.md`](../../OUTLINE_4DAY.md) Day2 下午 ★坑卡
> 「lambda 槽的生命周期与第五参数」。手工维护,非生成产物。
## 概念
`connect` 的第五参数(context object)决定这条连接**跟谁的生命周期挂钩**:
- `connect(sender, signal, lambda)`——连接只跟 sender 挂钩,**接收方对象销毁后
lambda 仍会被调用**,捕获的指针就是悬空指针;
- `connect(sender, signal, receiver, lambda)`——receiver 析构时 Qt 自动断开
连接,lambda 不可能再访问已销毁的对象。
规则:**lambda 里捕获了某个 QObject,就把它作为第五参数传进去**。
## 运行结果解读
默认运行打印两次 emit 的对比:delete receiver 之后,只有「无 context」的连接
还在触发。`--dangle` 让这条 lambda 真的去访问已销毁对象——你可能看到程序崩溃,
也可能看到它**打印出看似正常的旧值**(刚释放的内存还没被复用)。后者更危险:
UB 在开发机上「看起来正常」,到了演示/交付现场才炸。
## 验证与演示方式
```bash
QT_QPA_PLATFORM=offscreen tools/run_qt.sh qt_pitfall_lambda_capture # 确定性对比输出,退出码 0
QT_QPA_PLATFORM=offscreen tools/run_qt.sh qt_pitfall_lambda_capture --dangle # 课堂演示:真实悬空访问(UB
```
## 练习方向(供任务卡引用)
- 把连接 A 的 lambda 改成按引用捕获一个局部 `QString`,在函数返回后触发信号,
分析这是哪一种悬空(对象悬空 vs 捕获变量悬空);
-`QObject::destroyed` 信号打印 receiver 的销毁时机,确认连接 B 断开发生在何时。
## 参考
- 本仓库对照:[`p03/ch04/lambda_signal_slot.cpp`](../../../../p03/ch04/lambda_signal_slot.cpp)lambda 槽基本写法)
- Qt 官方文档:*Differences between String-Based and Functor-Based Connections*(选读·需联网)