ObserverHandle通过RAII实现自动注册与注销:构造时注册、析构时注销,仅允许noexcept移动、禁止拷贝;回调容器采用副本通知或延迟队列避免迭代器失效;观察者需继承enable_shared_from_this并捕获shared_ptr确保this安全。

用ObserverHandle实现自动注册与注销
当观察者对象比被观察者先销毁时,裸存std::function回调会导致野指针调用崩溃,必须让注册动作与观察者生命周期严格绑定。这一步的核心是返回一个轻量句柄,它的构造即注册、析构即注销。
定义ObserverHandle类,仅允许移动、禁止拷贝:声明移动构造函数和移动赋值运算符为noexcept,显式删除拷贝构造与拷贝赋值;否则std::vector在扩容时可能因异常中止导致句柄泄漏。
ObserverHandle构造时接收一个std::function
析构函数中判空后执行m_unregister()——这是唯一触发反注册的地方,也是RAII生效的临界点。
立即学习“C++免费学习笔记(深入)”;
被观察者端的回调容器设计
被观察者内部用std::vector<:function>>存储回调最简可行,但通知时绝不能边遍历边修改容器。
方法一:副本通知机制。notify()内先加读锁(如std::shared_lock<:shared_mutex>),将原始容器浅拷贝到局部vector,释放锁后再遍历副本执行。这样即使某个回调内部调用unsubscribe也不会导致迭代器失效。
方法二:延迟队列模式。notify()不执行回调,而是把每个回调包装成捕获当前状态快照的lambda,push_back到m_pending_callbacks;后续在可控时机(如作用域末尾)调用flush_pending()统一派发,并用std::exchange(m_pending_callbacks, {})确保清空原子性。
两种方法都要求对每个回调执行前做if(cb)检查,防止move后残留空std::function引发bad_function_call。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
避免this悬挂的安全捕获方案
直接在lambda中捕获this是高危操作,因为无法保证this所指对象比被观察者活得久。必须切断this与回调的强绑定关系。
第一步:观察者类继承std::enable_shared_from_this
第二步:注册时使用shared_from_this()获取强引用,再通过lambda捕获该shared_ptr;
第三步:回调体写成[self = shared_from_this()]{ self->on_event(); },确保对象存活前提下才执行业务逻辑。
【若未继承enable_shared_from_this而强行调用shared_from_this(),程序将抛出std::bad_weak_ptr异常】。
移动-only句柄的正确持有方式
ObserverHandle必须作为观察者类的成员变量,且声明位置应在类定义末尾——这是为了确保其析构顺序晚于其他依赖回调的成员,防止注销时访问已析构成员。
初始化该成员时使用= default或委托构造,不可在构造函数体内手动调用subscribe并赋值句柄,否则会破坏RAII的确定性。
移动语义必须显式声明为noexcept,否则放入std::vector等容器时可能因异常安全要求退化为复制,进而触发重复注销。
ObserverHandle离开作用域时自动析构,无需任何手动干预。

















