手撕简易版的智能指针

目录

一、智能指针的通用模板

二、auto_ptr(禁止使用)

三、unique_ptr

四、shared_ptr

五、定制删除器(shared_ptr))


一、智能指针的通用模板

对于智能指针一般需实现构造、*、->、析构等函数,私有成员包括未定义类型的指针,至于拷贝构造和赋值重载按需实现。

cpp 复制代码
/*
    template<class T>
    class smartptr
    {
    public:
        smartptr(T*ptr):_ptr(ptr){}
        ~smartptr(){if(_ptr) delete _ptr;}
        T*operator->() { return _ptr; }
        T&operator*() { return *_ptr;}
        //拷贝构造和赋值构造......
    private:
        T*_ptr;
    };
    */

二、auto_ptr(禁止使用)

对于auto_ptr(关键实现管理权限的转移)仅供学习,禁止使用

注:

(1)权限的转移,所以构造赋值传参不能加const

(2)赋值重载时,

//1.自己=自己,直接返回自己本身

//2.自己=other,other先改变(释放)原指针的管理,在挂接到新的指针上

cpp 复制代码
template<class T>
    //权限的转移,所以构造赋值传参不能加const
    class auto_ptr
    {
    public:
        //无参与有参构造
        auto_ptr(T*ptr = nullptr) { _ptr = ptr; }
        T*operator->(){return _ptr;}
        T&operator*(){return *_ptr;}
        //拷贝构造
        auto_ptr(auto_ptr<T>&sp)
        {
            _ptr = sp._ptr;
            sp._ptr = nullptr;
        }
        void release()
        {
            if(_ptr)
                delete _ptr;
        }
        //赋值构造
        auto_ptr&operator=(auto_ptr<T>&sp)
        {
            //1.自己=自己,直接返回自己本身
            //2.自己=other,other先改变(释放)原指针的管理,在挂接到新的指针上
            if(_ptr != sp._ptr)
            {
                release();
                _ptr = sp._ptr;
                sp._ptr = nullptr;
            }
            return *this;
        }

        ~auto_ptr()
        {
            release();
        }
    private:
        T *_ptr;
    };

三、unique_ptr

主要是禁止拷贝构造和赋值重载

cpp 复制代码
template<class T>
    //禁止拷贝和赋值
    class unique_ptr
    {
    public:
        unique_ptr(T* ptr = nullptr) : _ptr(ptr) {}
        T*operator->() { return _ptr; }
        T&operator*() { return *_ptr;}
        ~unique_ptr()
        {
            if(_ptr) 
                delete _ptr;
        }
        T* get() const { return _ptr; }
        unique_ptr(const unique_ptr<T>&sp) = delete;
        unique_ptr&operator=(const unique_ptr<T>&sp) = delete;
    private:
        T *_ptr;
    };

四、shared_ptr

采用引用计数的方式进行智能指针的管理

注:

(1)//计数方式:
/*1.在堆上开辟一块空间进行计数的维护(make_shared的原理)
2.直接使用int私有成员,表示每一个对象一个计数这样就不合理
3.使用静态成员的话,所有类成员均可见,换一个对象再计数也不合理*/

(2)赋值重载和auto_ptr那相同注意点

cpp 复制代码
// //未加定制删除器
    // class shared_ptr
    // {
    // public:
    //     shared_ptr(T*ptr = nullptr) : _ptr(ptr), _count(new int(1)) {}
    //     shared_ptr(const shared_ptr<T>&sp)
    //     {
    //         _ptr = sp._ptr;
    //         _count = sp._count;
    //         (*_count)++;
    //     }
    //     void release()
    //     {
    //         if(--(*_count) == 0)
    //         {
    //             delete _ptr;
    //             delete _count;
    //         }
    //     }
    //     //1.自己=自己,直接返回自己本身
    //         //2.自己=other,自己先改变(释放)原指针的管理,在挂接到新的指针上
    //     shared_ptr&operator=(const shared_ptr<T>&sp)
    //     {
    //         if(_ptr != sp._ptr)
    //         {
    //             release();
    //             _ptr = sp._ptr;
    //             _count = sp._count;
    //             (*_count)++;
    //         }
    //         return *this;
    //     }
    //     ~shared_ptr()
    //     {
    //         release();
    //     }
    //     T*operator->() {return _ptr;}
    //     T&operator*() {return *_ptr;}
    //     int use_count() {return *_count;}
    //     T*get()const {return _ptr;}
    // private:
    //     T *_ptr;
    //     int *_count;
    // };

五、定制删除器(shared_ptr)

(特殊的函数类型传入相应的析构函数),完成正确的析构,避免内存泄漏

c++标准库引入定制删除器的方式:

//unique_ptr添加定制删除器是实例化模板添加,

unique_ptr<Date[ ]> / unique_ptr<Date[ ],delete[ ]>
//shared_ptr是函数构造时添加的表达式或者仿函数

shared_ptr<FILE> sp(fopen("text.cc),fclose(lambda表达式,函数指针,仿函数等))
仅简单手撕shared_ptr版本

注:

//若我们直接引入模板进行构造添加,eg:
/*template<class D>
shared_ptr(T*ptr,D del){}*/
//构造析构时无法实例化(类型)和传参lambda表达式和仿函数
//所以引入包装器function,可以对所有的lambda表达式和仿函数进行包装,不用考虑类型
//包装器传入后,对象析构时会调用对象对应的析构(删除器)如果没传的话会内存泄漏,因此我们要有默认形式:
//function<void(T*ptr)> _del = [](T*ptr){delete ptr;};

cpp 复制代码
class shared_ptr
    {
    public:
        shared_ptr(T*ptr = nullptr) : _ptr(ptr), _count(new int(1)) {}
        //定制删除器构造
        template<class D>
        shared_ptr(T*ptr,D del) : _ptr(ptr), _count(new int(1)),_del(del) {}
        shared_ptr(const shared_ptr<T>&sp)
        {
            _ptr = sp._ptr;
            _count = sp._count;
            (*_count)++;
        }
        void release()
        {
            if(--(*_count) == 0)
            {
                // delete _ptr;
                _del(_ptr);
                delete _count;
            }
        }
        //1.自己=自己,直接返回自己本身
            //2.自己=other,自己先改变(释放)原指针的管理,在挂接到新的指针上
        shared_ptr&operator=(const shared_ptr<T>&sp)
        {
            if(_ptr != sp._ptr)
            {
                release();
                _ptr = sp._ptr;
                _count = sp._count;
                (*_count)++;
            }
            return *this;
        }
        ~shared_ptr()
        {
            release();
        }
        T*operator->() {return _ptr;}
        T&operator*() {return *_ptr;}
        int use_count() {return *_count;}
        T*get()const {return _ptr;}
    private:
        T *_ptr;
        int *_count;
        function<void(T*ptr)> _del = [](T*ptr){delete ptr;};
    };
相关推荐
2401_8920709819 小时前
【Linux C++ 日志系统实战】LogFile 日志文件管理核心:滚动策略、线程安全与方法全解析
linux·c++·日志系统·日志滚动
yuzhuanhei20 小时前
Visual Studio 配置C++opencv
c++·学习·visual studio
不爱吃炸鸡柳20 小时前
C++ STL list 超详细解析:从接口使用到模拟实现
开发语言·c++·list
十五年专注C++开发20 小时前
RTTR: 一款MIT 协议开源的 C++ 运行时反射库
开发语言·c++·反射
‎ദ്ദിᵔ.˛.ᵔ₎20 小时前
STL 栈 队列
开发语言·c++
2401_8920709821 小时前
【Linux C++ 日志系统实战】高性能文件写入 AppendFile 核心方法解析
linux·c++·日志系统·文件写对象
郭涤生21 小时前
STL vector 扩容机制与自定义内存分配器设计分析
c++·算法
༾冬瓜大侠༿21 小时前
vector
c语言·开发语言·数据结构·c++·算法
cccyi721 小时前
【C++ 脚手架】etcd 的介绍与使用
c++·服务发现·etcd·服务注册
liu****21 小时前
第16届省赛蓝桥杯大赛C/C++大学B组(京津冀)
开发语言·数据结构·c++·算法·蓝桥杯