LiSheng's blog LiSheng's blog
首页
笔记
个人简历
随笔集
GitHub (opens new window)
首页
笔记
个人简历
随笔集
GitHub (opens new window)
  • golang

  • cplus

    • 内存相关

      • new、delete、malloc、free
      • 智能指针
        • 内存池
      • 面向对象

      • STL相关

      • 内置数据结构
      • 数据结构示例
      • go和c++对比
      • 关键字

    • leetcode

    • 存储技术

    • 分布式系统

    • 计算机网络

    • Linux操作系统

    • Redis

    • 其他

    • 笔记
    • cplus
    • 内存相关
    lisheng
    2024-09-10
    目录

    智能指针

    C++ 智能指针的底层实现是通过 RAII(Resource Acquisition Is Initialization,资源获取即初始化)和引用计数来管理动态分配的内存或资源,避免手动管理内存带来的问题,如内存泄漏和悬空指针。C++ 标准库中提供了几种常见的智能指针类型:std::unique_ptr、std::shared_ptr 和 std::weak_ptr。以下是它们的基本底层实现原理。

    # 1. std::unique_ptr

    std::unique_ptr 是一种独占所有权的智能指针,表示某个指针只能由一个 unique_ptr 拥有。当 unique_ptr 超出作用域时,自动销毁所管理的对象。

    # 底层实现

    • 成员变量: unique_ptr 通常持有一个原生指针,用于指向所管理的对象。

    • 构造与析构:

      • 在构造时,unique_ptr 接受一个原生指针,并将它存储在内部。
      • 在析构时,unique_ptr 会自动调用 delete 来销毁所管理的对象。
    • 禁止拷贝:

      • 通过删除拷贝构造函数和拷贝赋值操作符,确保 unique_ptr 的唯一所有权特性。
    • 移动语义:

      • 通过实现移动构造函数和移动赋值操作符,使得所有权可以在不同的 unique_ptr 之间转移。
    template<typename T>
    class unique_ptr {
    private:
        T* ptr;
    public:
        explicit unique_ptr(T* p = nullptr) : ptr(p) {}
    
        ~unique_ptr() {
            delete ptr;
        }
    
        unique_ptr(const unique_ptr&) = delete;
        unique_ptr& operator=(const unique_ptr&) = delete;
    
        unique_ptr(unique_ptr&& other) noexcept : ptr(other.ptr) {
            other.ptr = nullptr;
        }
    
        unique_ptr& operator=(unique_ptr&& other) noexcept {
            if (this != &other) {
                delete ptr;
                ptr = other.ptr;
                other.ptr = nullptr;
            }
            return *this;
        }
    
        T* get() const { return ptr; }
        T& operator*() const { return *ptr; }
        T* operator->() const { return ptr; }
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

    # 2. std::shared_ptr

    std::shared_ptr 是一种具有共享所有权的智能指针,允许多个 shared_ptr 实例管理同一个对象。当最后一个 shared_ptr 销毁时,对象才会被释放。

    # 底层实现

    • 成员变量:

      • 原生指针:指向被管理的对象。
      • 控制块(Control Block):存储引用计数、弱引用计数以及管理的对象的指针。
    • 控制块:

      • 引用计数:用于跟踪有多少个 shared_ptr 实例共享该对象。
      • 弱引用计数:用于跟踪 std::weak_ptr 实例的数量。
      • 当引用计数减为零时,释放对象;当弱引用计数也为零时,释放控制块。
    • 构造与析构:

      • 在构造时,创建或共享控制块,并增加引用计数。
      • 在析构时,减少引用计数。如果引用计数为零,则释放所管理的对象。
    • 线程安全:

      • shared_ptr 的引用计数操作是线程安全的。
    template<typename T>
    class shared_ptr {
    private:
        T* ptr;
        ControlBlock* controlBlock;
    
    public:
        shared_ptr(T* p = nullptr) : ptr(p) {
            if (ptr) {
                controlBlock = new ControlBlock(p);
            }
        }
    
        ~shared_ptr() {
            if (controlBlock && --controlBlock->ref_count == 0) {
                delete ptr;
                if (controlBlock->weak_count == 0) {
                    delete controlBlock;
                }
            }
        }
    
        shared_ptr(const shared_ptr& other) : ptr(other.ptr), controlBlock(other.controlBlock) {
            if (controlBlock) {
                ++controlBlock->ref_count;
            }
        }
    
        shared_ptr& operator=(const shared_ptr& other) {
            if (this != &other) {
                // 减少旧的引用计数
                if (controlBlock && --controlBlock->ref_count == 0) {
                    delete ptr;
                    if (controlBlock->weak_count == 0) {
                        delete controlBlock;
                    }
                }
                // 增加新的引用计数
                ptr = other.ptr;
                controlBlock = other.controlBlock;
                if (controlBlock) {
                    ++controlBlock->ref_count;
                }
            }
            return *this;
        }
    
        T* get() const { return ptr; }
        T& operator*() const { return *ptr; }
        T* operator->() const { return ptr; }
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51

    # 3. std::weak_ptr

    std::weak_ptr 是与 shared_ptr 搭配使用的智能指针,它不影响所管理对象的生命周期,而是提供对 shared_ptr 所管理对象的弱引用。它主要用于解决循环引用问题。

    # 底层实现

    • 弱引用:

      • weak_ptr 持有对控制块的弱引用,而不直接持有对对象的引用。
      • 当 weak_ptr 需要访问对象时,会尝试提升(lock)为 shared_ptr,如果对象已被销毁,则提升失败。
    • 控制块:

      • weak_ptr 的创建和销毁会影响控制块中的弱引用计数,但不影响对象的引用计数。

    # 4. 总结

    • std::unique_ptr 提供了简单而高效的独占所有权管理,避免了复制和共享。
    • std::shared_ptr 使用引用计数管理共享对象的生命周期,支持多方共享同一资源。
    • std::weak_ptr 通过弱引用解决了循环依赖问题,在不增加引用计数的情况下访问对象。
    编辑 (opens new window)
    上次更新: 2024/09/13, 11:59:12
    new、delete、malloc、free
    内存池

    ← new、delete、malloc、free 内存池→

    最近更新
    01
    ceph分布式存储-对象存储(RGW)搭建
    10-27
    02
    ceph分布式存储-集群客户端连接
    10-27
    03
    ceph分布式存储-管理crushmap
    10-27
    更多文章>
    Theme by Vdoing
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式