跳转至

智能指针

unique_ptr

定义了这个对象在程序中只有一份数据,任何拷贝、赋值都是一样的,不会增加数据

简单实现:

template<typedef T>             // 将类中的指针类型设置成模板
class unique_ptr{
    public:
        explicit unique_ptr(T* ptr=nullptr):ptr_(ptr){}     // 设置构造函数初始化指针 explicit防止隐式转换
        ~unique(){
            delete ptr_;
        }
        T* get()const noexcept{return ptr_;}

        // pointer-like 要表示出指针应该有的特性
        T& operator*()const noexcept{return *ptr_;}
        T* operator->()const noexcept{return ptr_;}
        operator bool()const noexcept{return ptr_;}

        // 释放指针所有权
        T* release(){
            T* ptr=ptr_;
            ptr_=nullptr;
            return ptr;
        }

        // 成员的交换函数(交换指针所有权) 利用的是std下的swap
        void swap(unique_ptr& rhs){
            using std::swap;
            swap(ptr_,rhs.ptr_);
        }

        // 接下来写上移动构造函数和赋值函数
        template<typedef U>
        unique_ptr(unique_ptr<U>&& other){
            // 函数的参数是右值引用,也就是说传入的参数必须是一个右值(将亡值)
            ptr_=other.release();       // 移动构造函数中释放传入参数指针所有权(要求不产生额外的对象)
        }

        unique_ptr& operator=(unique_ptr other){    // 传入参数为:值拷贝    调用的是移动构造函数,省去了在函数内构造临时对象的语句
            other.swap(*this);      // 拷贝一份交换指针所有权
            return *this;
        }

    private:
        T* ptr_;
};

shared_ptr

多用来计数,能在不用到对象时自动释放内存,防止内存泄漏

// 计数类
class share_count{
    public:
        explicit share_count():count(1){}           // 计数值初始化为 1
        void add_count(){
            ++count;            // 并不关心增加了多少数
        }
        long reduce_count(){
            return --count;         // 只关心还剩下多少数
        }
        long use_count(){
            return count;
        }

    private:
        long count;
};

// 指针类  设置为模板
template<typedef T>
class shared_ptr{
    template<typedef U>
    friend class shared_ptr;        // 将其他类型的指针类作为友元,方便操作其他类型的成员变量

    public:
        explicit shared_ptr(T* ptr=nullptr){        // 显示初始化指针和计数器
            if(ptr){
                share_count_=new share_count();
            }
        }
        ~shared_ptr(){          // 析构函数:指针存在计数值还没减到0时,释放内存
            if(ptr_ && !share_count_->reduce_count()){
                delete ptr_;
                delete share_count_;
            }
        }

        // 拷贝构造函数:计数器加1,对方指针直接赋值(共享)
        shared_ptr(shared_ptr& other) noexcept{
            ptr_=other.ptr_;
            if(ptr_){
                other.share_count_->add_count();
                share_count_=other.share_count_;
            }
        }

        // 模板类移动构造函数:指针和计数器直接转移
        template<typedef U>
        shared_ptr(shared_ptr<U>&& other) noexcept{
            ptr_=other.ptr_;
            if(ptr_){
                share_count_=other.share_count_;
                other.share_count_=nullptr;
            }
        }

        // 赋值:传入值拷贝,调用移动构造函数还是拷贝构造函数,取决于传入的参数是右值还是左值
        shared_ptr& operator=(shared_ptr rhs) noexcept{
            rhs.swap(*this);
            return *this;
        }

        void swap(shared_ptr& rhs){
            using std::swap;
            swap(ptr_,rhs.ptr_);
            swap(share_count_,rhs.share_count_);
        }
        T* get(){
          return ptr_;  
        }

        // 为了类外几种类型转换定义需要
        template<typedef U>
        shared_ptr(shared_count<U>& other,T* ptr) noexcept{
            ptr_=ptr;
            if(ptr_){
                other.share_count_->add_count();
                share_count_=other.share_count_;
            }
        }


        // 指针特征
        T& operator*()const noexcept{
            return *ptr_;
        }
        T* operator->()const noexcept{
            return ptr_;
        }
        operator bool()const noexcept{
            return ptr_;
        }

    private:
        T* ptr_;
        share_count* shanre_count_;
};

// 全局的交换函数
template<typedef T>
void swap(shared_ptr<T>& lhs,shared_ptr<T>& rhs){
    lhs.swap(rhs);
}

// static_cast 转换函数定义
template<typedef T,typedef U>
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& other){
    T* ptr=static_cast<T*>(other.get());    // 指针转型
    return shared_ptr(other,ptr);       // 再传回去构造生成新的类型
}

// 下同
template<typedef T,typedef U>
shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& other){
    T* ptr=static_cast<T*>(other.get());
    return shared_ptr(other,ptr);
}

template<typedef T,typedef U>
shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& other){
    T* ptr=reinterpret_cast<T*>(other.get());
    return shared_ptr(other,ptr);
}

template<typedef T,typedef U>
shared_ptr<T> const_pointer_cast(const shared_ptr<U>& other){
    T* ptr=const_cast<T*>(other.get());
    return shared_ptr(other,ptr);
}