c++智能指针实现(二)shared_ptr unique_ptr的实现

下面是对shared_ptr 和 unique_ptr这两种类的简单实现。

shared_ptr

template<typename T>
struct DefaultDeleter {
    void operator()(T *ptr) {
        if (nullptr != ptr) {
            delete ptr;
            ptr = nullptr;
        }
    }
};

template <typename T>
class SharedPtr {
 public:
    SharedPtr() : pointer_{nullptr}, reference_count_{nullptr} {}

    SharedPtr(T* pointer, std::function<void(T*)> deleter=DefaultDeleter<T>())
        : pointer_{pointer}, reference_count_{nullptr} {
        add_reference_count();
        deleter_ = deleter;
    }

    SharedPtr(const SharedPtr<T>& copy) {
        if (this != &copy) {
            this->pointer_ = copy.pointer_;
            this->reference_count_ = copy.reference_count_;
            add_reference_count();
        }
    }

    SharedPtr& operator=(const SharedPtr<T>& other) {
        if (this != &other) {
            remove_reference_count();
            this->pointer_ = other.pointer_;
            this->reference_count_ = other.reference_count_;
            this->deleter_ = other.deleter_;
            add_reference_count();
        }
        return *this;
    }

    bool operator==(const SharedPtr<T>& other) {
        return this->pointer_==other.pointer_;
    }

    bool operator!=(const SharedPtr<T>& other) {
        return !operator==(other);
    }

    T* operator*() {
        assert(nullptr == pointer_);
        return (*pointer_);
    }

    T operator->() const {
        return pointer_;   
    }

    int use_count() {
        if (nullptr != reference_count_) {
            return *reference_count_;
        } else {
            return 0;
        }
    }

    void reset(T *ptr) {
        remove_reference_count();
        pointer_ = ptr;
    }

    T* get() {
        return pointer_;
    }

    ~SharedPtr() {
        remove_reference_count();
    }

 private:
    void add_reference_count() {
        if (nullptr != reference_count_) {
            (*reference_count_)++;
        } else {
            reference_count_ = new size_t(1U);
        }
    }

    void remove_reference_count() {
        if (nullptr !=reference_count_) {
            (*reference_count_)--;
            if ((*reference_count_) == 0) {
                deleter_(pointer_);
                delete reference_count_;
                pointer_ = nullptr;
                reference_count_ = nullptr;
            }
        }
    }

    T* pointer_;
    size_t* reference_count_;
    std::function<void(T*)> deleter_;
};

这里reference_count_和pointer_一样都是指针类型,是为达到共享的目的,在各个SharedPtr都需要知道引用计数的值,并且都可以修改。在传入删除器时,默认是delete的方式,有传入自定义的删除器时使用自定义的删除器。
引用计数这一点和之前看到过的string类的copy-on-write实现挺类似的,感兴趣的同学可以看一下这篇文章:https://blog.csdn.net/haoel/article/details/24058。

unique_ptr

template <typename T, typename Deleter = DefaultDeleter<T>>
class UniquePtr {
 public:
    UniquePtr(T* ptr = nullptr) : pointer_{ptr} {};

    UniquePtr(const UniquePtr& ptr)=delete;

    UniquePtr& operator=(const UniquePtr& ptr)=delete;

    ~UniquePtr() {
        if (nullptr != pointer_) {
            deleter_(pointer_);
            pointer_ = nullptr;
        }
    }

    T* release() {
        T* ret_ptr = pointer_;
        pointer_ = nullptr;
        return ret_ptr;
    }

    T* get() {
        return pointer_;
    }

    T& operator*() {
        return *pointer_;
    }

    T* operator->() {
        return pointer_;
    }

    void reset(T* ptr) {
        if (nullptr != pointer_) {
            deleter_(pointer_);
        }
        pointer_ = ptr;
    }

    operator bool() const {
        return nullptr != pointer_;
    }

 private:
    T* pointer_;
    Deleter deleter_;
};

可以看到,UniquePtr的拷贝的构造和赋值构造都delete了,实现了独享。默认的删除器还是detele。


对于std::shared_ptr和std::unique_ptr来讲,指定删除器还是有区别的。unique_ptr制定删除器时必须明确删除器的类型,在编译时绑定。而对于shared_ptr来说,删除器类型是在运行时绑定。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值