C++11智能指针-解析

一、智能指针的基本概念

C++11 中引入了智能指针(Smart Pointer),本质就是一个类模板。它利用了一种叫做 RAII(资源获取即初始化)的技术将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放该指针所指向的内存空间,从而防止内存泄漏。这使得智能指针实质是一个对象,行为表现的却像一个指针。

二、智能指针的简单实现

#include<mutex>

template<typename T>
class Shared_ptr {
private:
    // 成员变量
    T *ptr_{nullptr};
    int *ref_count_{nullptr};
    std::mutex *mutex_{nullptr};
public:
    /******************** 构造函数和析构函数 ********************/
    // 默认构造函数
    constexpr Shared_ptr() noexcept = default;

    // 普通构造函数
    explicit Shared_ptr(T *ptr) : ptr_{ptr} {
        if (this->ptr_ != nullptr) {
            this->ref_count_ = new int{1};
            this->mutex_ = new std::mutex{};
        }
    }

    // 从四行代码看右值引用:https://www.cnblogs.com/qicosmos/p/4283455.html
    // - move 本意为 "移动",但该函数并不能移动任何数据,它的功能很简单,就是将某个左值强制转化为右值。
    // - forward 完美转发,根据右值判断的推倒,调用forward 传出的值,若原来是一个右值,那么他转出来就是一个右值,否则为一个左值。这样的处理就完美的转发了原有参数的左右值属性,不会造成一些不必要的拷贝

    // 拷贝构造函数
    Shared_ptr(const Shared_ptr &rhs) noexcept: ptr_{rhs.ptr_}, ref_count_{rhs.ref_count_}, mutex_{rhs.mutex_} {
        if (this->ptr_ != nullptr) {
            this->addRefCount();
        }
    }

    // 移动构造函数
    Shared_ptr(Shared_ptr &&rhs) noexcept: ptr_{rhs.ptr_}, ref_count_{rhs.ref_count_}, mutex_{rhs.mutex_} {
        // right hand side is nullptr
        rhs.ptr_ = nullptr;
        rhs.ref_count_ = nullptr;
        rhs.mutex_ = nullptr;
    }

    // 析构函数
    ~Shared_ptr() noexcept {
        this->decrRefCount();
    }

    /******************** 运算符重载 ********************/
    // 拷贝赋值运算符
    Shared_ptr &operator=(const Shared_ptr &rhs) {
        Shared_ptr{rhs}.swap(*this);
        return *this;
    }

    // 移动赋值运算符
    Shared_ptr &operator=(Shared_ptr &&rhs) noexcept {
        Shared_ptr{std::move(rhs)}.swap(*this);
        return *this;
    }

    // 取值
    T &operator*() const noexcept {
        return *this->ptr_;
    }

    // 取指针
    T &operator->() const noexcept {
        return this->ptr_;
    }

    // 到 bool 的隐式转换
    explicit operator bool() const noexcept {
        return static_cast<bool>(ptr_);
    }

    /******************** 成员函数 ********************/
    // 获取指针
    T *get() const noexcept {
        return ptr_;
    }

    // 获取引用计数
    int use_count() const noexcept {
        return this->ref_count_ == nullptr ? 0 : *this->ref_count_;
    }

    // 引用计数是否唯一
    bool unique() const noexcept {
        return *this->ref_count_ == 1;
    }

    // 重置指针
    void reset() noexcept {
        Shared_ptr{}.swap(*this);
    }

    // 重置指针
    void reset(T *ptr) {
        Shared_ptr{ptr}.swap(*this);
    }

    // swap函数
    void swap(Shared_ptr &rhs) noexcept {
        std::swap(this->ptr_, rhs.ptr_);
        std::swap(this->ref_count_, rhs.ref_count_);
        std::swap(this->mutex_, rhs.mutex_);
    }

private:
    // 增加引用计数
    void addRefCount() {
        mutex_->lock();
        ++(*ref_count_);
        mutex_->unlock();
    }

    // 减少引用计数,如果为零,则释放指针
    void decrRefCount() {
        bool deleteflag = false;
        mutex_->lock();
        if (--(*ref_count_) == 0) {
            delete ptr_;
            delete ref_count_;
            deleteflag = true;
        }
        mutex_->unlock();
        if (deleteflag) {
            delete mutex_;
        }
    }
};

// 函数模板
template<typename T>
auto make_Shared(T v) {
    return Shared_ptr<T>{new T(v)};
}

三、智能指针的应用

#include <iostream>
#include <memory>

using namespace std;

int main() {
    // make_Shared
    {
        Shared_ptr<int> p1 = make_Shared<int>(42);
        Shared_ptr<int> p2 = p1;
        cout << *p1 << endl;
        cout << p1.use_count() << endl;
        cout << p1.unique() << endl;
    }
    // shared_ptr
    {
        // 初始化
        shared_ptr<int> p1 = make_shared<int>(42);
        shared_ptr<int> p2(new int(1024));
        shared_ptr<int> p3 = p2;
        // 获取值
        cout << p1.get() << endl;
        cout << *p1.get() << endl;
        cout << *p1 << endl;
        // 引用计数
        cout << p1.use_count() << endl;
        cout << p2.use_count() << endl;
        cout << p3.use_count() << endl;
        // 引用计数是否唯一
        cout << p1.unique() << endl;
        // 重置
        p1.reset(new int(322));
        // swap
        p1.swap(p2);
    }
    // weak_ptr
    {
        shared_ptr<int> p = make_shared<int>(42);
        weak_ptr<int> w(p);    // 与p指向相同对象的weak_ptr, T必须能转换为sp指向的类型
        w = p;    // p可以是shared_ptr或者weak_ptr,赋值后w和p共享对象
        w.reset();    // weak_ptr置为空
        w.use_count();    // 与w共享对象的shared_ptr的计数
        w.expired();    // w.use_count()为0则返回true,否则返回false
        w.lock();    // w.expired()为true,返回空的shared_ptr;否则返回指向w的shared_ptr
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值