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

std::weak_ptr应用于观察者模式的示例

在 C++ 中,std::weak_ptr 是一个智能指针,用来观察由 std::shared_ptr 所管理的对象,而不增加该对象的引用计数。它通常用于避免 循环引用强引用计数的增长,特别在实现观察者模式时,weak_ptr 可以帮助观察者避免不必要的对象生命周期延长。

以下是如何使用 std::weak_ptr 来实现一个简单的观察者模式的示例。

观察者模式简介

观察者模式是一种行为设计模式,其中一个对象(主题或发布者)维护一组依赖对象(观察者),并在状态变化时通知这些观察者。主题对象的生命周期通常较长,而观察者对象的生命周期通常较短,使用 weak_ptr 可以确保观察者在主题对象销毁时不会导致内存泄漏。

示例:使用 weak_ptr 实现观察者模式

下面是一个简单的例子,其中我们有一个 Subject 类(主题),它可以注册多个 Observer(观察者)。每个观察者是通过 std::weak_ptr 来持有的,避免循环引用。

1. 定义 ObserverSubject
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>

class Observer {
public:
    virtual void update(int value) = 0;
    virtual ~Observer() = default;
};

class Subject {
private:
    std::vector<std::weak_ptr<Observer>> observers;

public:
    void addObserver(const std::shared_ptr<Observer>& observer) {
        observers.push_back(observer);
    }

    void removeObserver(const std::shared_ptr<Observer>& observer) {
        observers.erase(std::remove_if(observers.begin(), observers.end(),
            [&](const std::weak_ptr<Observer>& o) { return o.lock() == observer; }), observers.end());
    }

    void notify(int value) {
        for (auto& weakObserver : observers) {
            if (auto observer = weakObserver.lock()) {  // 如果观察者仍然存在
                observer->update(value);
            }
        }
    }
};
2. 定义具体的 Observer 实现
class ConcreteObserver : public Observer {
private:
    std::string name;

public:
    ConcreteObserver(const std::string& name) : name(name) {}

    void update(int value) override {
        std::cout << "Observer " << name << " received update with value: " << value << std::endl;
    }
};
3. 使用 SubjectObserver
int main() {
    // 创建主题对象
    std::shared_ptr<Subject> subject = std::make_shared<Subject>();

    // 创建观察者对象
    std::shared_ptr<ConcreteObserver> observer1 = std::make_shared<ConcreteObserver>("Observer1");
    std::shared_ptr<ConcreteObserver> observer2 = std::make_shared<ConcreteObserver>("Observer2");

    // 注册观察者
    subject->addObserver(observer1);
    subject->addObserver(observer2);

    // 通知观察者
    subject->notify(10);  // 所有观察者都会接收到通知

    // 移除一个观察者
    subject->removeObserver(observer1);

    // 通知剩余的观察者
    subject->notify(20);  // 只有 Observer2 会接收到通知

    // observer2 会自动销毁,而 observer1 的析构函数不会被触发
    return 0;
}

解释

  1. 观察者和主题:

    • Observer 是一个抽象类,定义了 update 方法,所有具体的观察者类都需要实现该方法。
    • Subject 是主题类,管理所有的观察者。它使用 std::weak_ptr<Observer> 来存储观察者,以避免观察者对象的生命周期被 Subject 锁住。
  2. weak_ptr 使用:

    • Subject 中,观察者是通过 std::weak_ptr<Observer> 存储的。weak_ptr 不会增加观察者的引用计数,避免了循环引用的问题。使用时,需要调用 lock() 方法来获取一个有效的 shared_ptr,如果观察者已经被销毁(引用计数为 0),lock() 会返回一个空指针。
  3. 观察者的生命周期管理:

    • main 函数中,我们创建了两个观察者对象,并注册到主题对象中。当我们通过 subject->notify() 向观察者发送通知时,只有有效的观察者会接收到通知。
    • 当一个观察者被从 Subject 中移除后,它将不再接收到通知。
    • std::weak_ptr 确保即使观察者对象在通知过程中销毁,它也不会阻止观察者对象的销毁。
  4. 移除观察者:

    • removeObserver 方法移除了特定的观察者。我们使用 std::remove_if 来从观察者列表中删除对应的观察者。如果该观察者已经被销毁,lock() 将返回 nullptr,该观察者将不会再被通知。

总结

使用 std::weak_ptr 可以有效地避免观察者模式中的循环引用问题,避免因为观察者持有主题对象的 shared_ptr 而导致无法销毁的问题。在这个示例中,Subject 类管理观察者的生命周期,而每个 Observer 使用 weak_ptr 观察主题对象,从而实现了避免循环引用和内存泄漏的功能。


http://www.kler.cn/a/404342.html

相关文章:

  • uniapp开发微信小程序笔记3-全局配置、导航栏配置、tabBar配置
  • SOA(面向服务架构)全面解析
  • iOS应用网络安全之HTTPS
  • HarmonyOS鸿蒙系统上File文件常用操作
  • 泷羽sec学习打卡-网络七层杀伤链1
  • 【Nginx从入门到精通】05-安装部署-虚拟机不能上网简单排错
  • 点亮创新之光:常用缺陷检测算法原理、介绍与发文突破方向全解
  • 持续集成与持续部署:CI/CD实现教程
  • C#之WPF的C1FlexGrid空间的行加载事件和列事件变更处理动态加载的枚举值
  • QT实现列表通过向上向下翻页按钮翻页,以及上下键逐行显示文本行,向左向右键翻页功能
  • 图论之最小生成树计数(最小生成树的应用)
  • 使用API有效率地管理Dynadot域名,删除账户中的whois联系人信息
  • 在 Linux 中,重启命令reboot
  • Linux 用户管理
  • Python简介以及解释器安装(保姆级教学)
  • 一文解读数据仓库的分层逻辑和原理
  • 【Linux从青铜到王者】Linux进程间通信(一)——待完善
  • Python设计模式详解之1 —— 单例模式
  • 例题10-4 冒泡排序 字符串排序
  • Web3游戏先锋 Big Time Studios 重磅推出 $OL 通证,赋能 Open Loot 游戏平台
  • Centos 7 安装 Docker 最新版本
  • 「OpenCV交叉编译」ubuntu to arm64
  • 刘艳兵-DBA042-下述哪些文件是在CREATE DATABASE命令中创建的?
  • 无重复字符的最长子串习题分析
  • 机器翻译基础与模型 之三:基于自注意力的模型
  • 实验室管理智能化:Spring Boot技术实现