智能指针

5 阅读2分钟

智能指针是C++中用于管理动态内存的工具,本质是一个封装了原始指针的类,通过RAII机制在对象生命周期结束时自动释放资源,从而避免内存泄漏。

其中unique_ptr表示独占所有权,shared_ptr通过引用计数实现共享所有权,weak_ptr用于解决shared_ptr循环引用的问题。

RAII:资源获取即初始化

在对象的构造函数中申请并分配资源。

利用 C++ 局部对象生命周期结束时自动调用析构函数的特性,在析构函数中释放资源。

#include <atomic>
#include <utility> //swap
#include <iostream>


template <typename T>
class SharedPtr
{
public:
    //构造
    explicit SharedPtr(T* ptr = nullptr)
                 : ptr_(ptr), 
                ref_count_(nullptr)
    {
        if (ptr_ != nullptr)
        {
            ref_count = new std::atomic<int>(1);
        }
    }

    //拷贝构造
    SharedPtr(const SharedPtr& other)
         : ptr_(other.ptr_), 
        ref_count_(other.ref_count_)
    {
        if (ref_count_ != nullptr)
        {
            ref_count_ -> fetch_add(1, std::memory_order_relaxed);
        }
    }

    //移动构造
    SharedPtr(SharedPtr&& other) noexcept
        : ptr_(other.ptr_),
        ref_count_(other.ref_count_)
    {
        other.ptr_ = nullptr;
        other.ref_count = nullptr;
    }

    //拷贝赋值
    SharedPtr& operator=(const SharedPtr& other)
    {
        if (this != &other)
        {
            //先减少当前对象的引用计数
            release();

            //复制新对象
            ptr_ = other.ptr_;
            ref_count_ = other.ref_count_;
            if (ref_count_ != nullptr)
            {
                ref_count_->fetch_add(1, std::memory_order_relaxed);
            }
        }
        return *this;
    }

    //移动赋值
    SharedPtr& operator=(SharedPtr&& other)
    {
        if (this != &other)
        {
            release();
            ptr_ = other.ptr_;
            ref_count_ = other.ref_count_;
            other.ptr_ = nullptr;
            other.ref_count_ = nullptr;
        }
        return *this;
    }
    
    //析构
    ~SharedPtr()
    {
        release();
    }


    //解引用
    T& operator*() const
    {
        return *ptr_;
    }
    T* operator->() const{
        return ptr_;
    }
    //获取原始指针
    T* get() const
    {
        return ptr_;
    }
    //获取引用计数
    int use_count() const
    {
        return ref_count_ != nullptr ? ref_count_->load(std::memory_order_relaxed) : 0;
    }
    //检查是否独占
    bool unique() const
    {
        return use_count() == 1;
    }
    //重置
    void reset(T* ptr = nullptr)
    {
        release();
        ptr_ = ptr;
        if (ptr_ != nullptr)
        {
            ref_count_ = new std::atomic<int>(1);
        }
        else{
            ref_count_ = nullptr;
        }
    }
    //交换
    void swap(SharedPtr& other)
    {
        std::swap(ptr_, other.ptr_);
        std::swap(ref_count_, other.ref_count_);
    }
private:
    void release()
    {
        if (ref_count_ != nullptr)
        {
            //减少引用计数
            int old_count = ref_count_->fetch_sub(1, std::memory_order_acq_rel);
            //最后一个引用,删除资源
            if (old_count == 1)
            {
                delete ptr_;
                delete ref_count_;
            }
        }
        ptr_ = nullptr;
        ref_count_ = nullptr;
    }
private:
    T* ptr_;
    std::atomic<int>* ref_count_;
};