# 坑点复现：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*（选读·需联网）
