手撕简易版的智能指针

目录

一、智能指针的通用模板

二、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;};
    };
相关推荐
basketball61616 小时前
C++ 嵌套类完全指南:类中类的巧妙设计
开发语言·c++
kyle~16 小时前
ros_gz_bridge---底层通信的实现
c++·机器人·仿真·ros2
Jasmine_llq16 小时前
《B4261 [GESP202503 三级] 2025》
开发语言·c++·算法·条件判断算法·位运算恒等式推导·简单算术运算
小张成长计划..16 小时前
【C++】32:智能指针
c++
咩咦16 小时前
C++学习笔记19:运算符重载基础与赋值运算符重载
c++·学习笔记·类和对象·运算符重载·赋值运算符·operator
无限进步_18 小时前
C++异常机制:抛出、捕获与栈展开
开发语言·c++·安全
王老师青少年编程18 小时前
csp信奥赛C++高频考点专项训练之前缀和&差分 --【一维前缀和】:宝石串
c++·前缀和·csp·高频考点·信奥赛·宝石串
梓䈑18 小时前
【算法题攻略】模拟
c++·算法
vKd0Ff21L18 小时前
如何在Dev-C++中设置TDM-GCC为默认编译器第九十一篇
java·jvm·c++
cany100018 小时前
C++ -- 型号比对和constexpr
c++