模拟实现weak_ptr

  • weak_ptr是为了解决shared_ptr的循环引用的问题
  • weak_ptr没有引用计数, 只是有一个获取资源的lock()函数
template <class T>
class weakPtr{
public:
	weakPtr(const sharedPtr& shPtr = nullptr)
		:_shPtr(&shPtr){
		;
	}

	//提供一个lock,来获取shared_ptr
	sharedPtr* Lock(){
		if (*(_shPtr->_ptrCount) > 0){
			return _shPtr;
		}
		else
		{
			return nullptr;
		}
	}
private:
	sharedPtr<T>* _shPtr;
};
<think>好的,我现在需要回答用户关于观察者模式中使用weak_ptr的问题,特别是气象站通知订阅者的例子。首先,我得回顾一下观察者模式的基本概念。观察者模式通常用于对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知。这里的关键是解耦主题和观察者,让它们可以独立变化。 用户提到使用weak_ptr来避免影响订阅者的生命周期。这涉及到C++中的智能指针,特别是shared_ptrweak_ptr的区别。传统的观察者模式中,主题持有观察者的指针或引用。如果使用shared_ptr,主题会保持对观察者的强引用,可能导致观察者无法正确释放,从而引发内存泄漏。这时候weak_ptr就派上用场了,因为它不会增加引用计数,只是弱引用,允许检查所指向的对象是否还存在。 接下来,我需要构思一个气象站的例子。气象站作为主题(Subject),当天气数据更新时,通知所有订阅的观察者(比如显示屏或手机应用)。观察者需要注册到气象站,而气象站应该使用weak_ptr来保存观察者的引用。这样,当观察者被销毁时,气象站不会阻止其析构。 需要注意的几个步骤:定义Observer接口,Subject类管理weak_ptr的观察者列表,在通知时检查weak_ptr是否有效。另外,观察者注册和注销的方法需要处理weak_ptr的转换。当气象站更新数据时,遍历观察者列表,尝试将weak_ptr转换为shared_ptr,如果成功则调用更新方法,否则从列表中移除失效的观察者。 可能存在的一些问题:使用weak_ptr时,如何安全地访问观察者。必须确保在调用观察者的方法时,对象仍然存在。因此,在通知前,需要将weak_ptr转换为shared_ptr,如果转换成功,说明对象还存在,可以安全调用;否则,说明观察者已经被销毁,应从列表中移除。 另外,线程安全的问题也需要考虑。如果在多线程环境下,观察者的添加、移除和通知操作可能需要加锁,但例子中可能暂时忽略这一点,专注于核心逻辑。 现在,我需要把这些思考整理成一个清晰的例子,用代码展示如何用weak_ptr实现观察者模式的气象站和订阅者。确保代码中的关键点都得到体现,比如Subject持有weak_ptr的列表,通知时的转换和有效性检查,以及如何注册和注销观察者。 最后,验证这个例子是否符合用户的需求:气象站通知订阅者而不影响其生命周期。即当观察者被销毁后,气象站不会保留无效的指针,也不会阻止其析构。通过weak_ptr的使用,确保主题和观察者之间的正确生命周期管理。</think>观察者模式使用weak_ptr的C++实现示例(气象站场景): ```cpp #include <memory> #include <vector> #include <algorithm> // 观察者接口 class WeatherObserver { public: virtual ~WeatherObserver() = default; virtual void update(float temp) = 0; }; // 主题基类 class WeatherStation { protected: std::vector<std::weak_ptr<WeatherObserver>> observers; public: void addObserver(std::weak_ptr<WeatherObserver> obs) { observers.push_back(obs); } void removeObserver(std::weak_ptr<WeatherObserver> obs) { observers.erase( std::remove_if(observers.begin(), observers.end(), [&](const auto& weakObs) { auto sharedObs = weakObs.lock(); auto target = obs.lock(); return sharedObs && target && sharedObs == target; }), observers.end()); } void notifyObservers(float temperature) { auto it = observers.begin(); while (it != observers.end()) { if (auto sharedObserver = it->lock()) { sharedObserver->update(temperature); ++it; } else { it = observers.erase(it); } } } }; // 具体观察者 class Display : public WeatherObserver { public: void update(float temp) override { std::cout << "Display: 当前温度 " << temp << "℃\n"; } }; // 使用示例 int main() { auto station = std::make_unique<WeatherStation>(); // 创建两个显示器 auto display1 = std::make_shared<Display>(); auto display2 = std::make_shared<Display>(); // 注册观察者(使用weak_ptr) station->addObserver(display1); station->addObserver(display2); // 模拟温度更新 station->notifyObservers(25.5f); // 两个显示器都会收到通知 // 销毁一个观察者 display2.reset(); // 再次通知 station->notifyObservers(26.0f); // 只有display1收到通知 // 自动清理失效的观察者 return 0; } ``` 关键实现要点: 1. 弱引用管理: - 使用`std::vector<std::weak_ptr<WeatherObserver>>`保存观察者 - 添加观察者时存储weak_ptr而非shared_ptr 2. 生命周期安全: - 调用notifyObservers()时通过lock()获取临时shared_ptr - 若返回空指针则自动清理失效观察者 - 观察者销毁时不会因主题持有引用而延长生命周期 3. 优势体现: - 当display2被reset()后,下次通知时会自动移除失效指针 - 主题不会阻止观察者的正常析构 - 避免循环引用导致的内存泄漏 4. 线程安全扩展: - 可添加互斥锁保护observers容器 - 使用std::recursive_mutex配合lock_guard - 通知时复制观察者列表以避免迭代时修改容器 典型应用场景: - GUI事件监听 - 实时数据监控系统 - 游戏中的成就系统 - 分布式系统中的心跳检测 这种模式特别适合需要动态管理观察者生命周期的场景,能够有效防止因观察者对象销毁导致的野指针问题,同时保持主题和观察者之间的松耦合关系。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值