手撕简易版的智能指针

目录

一、智能指针的通用模板

二、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;};
    };
相关推荐
浒畔居2 小时前
泛型编程与STL设计思想
开发语言·c++·算法
Fcy6482 小时前
C++ 异常详解
开发语言·c++·异常
机器视觉知识推荐、就业指导2 小时前
Qt 和 C++,是不是应该叫 Q++ 了?
开发语言·c++·qt
liu****3 小时前
三.Qt图形界面开发完全指南:从入门到掌握常用控件
开发语言·c++·qt
小龙报3 小时前
【C语言进阶数据结构与算法】单链表综合练习:1.删除链表中等于给定值 val 的所有节点 2.反转链表 3.链表中间节点
c语言·开发语言·数据结构·c++·算法·链表·visual studio
EmbedLinX3 小时前
Linux之内存管理
linux·服务器·c语言·c++
南岩亦凛汀4 小时前
快速上手Ultimate++的编译链接和配置
c++·gui·开源框架
CoderCodingNo4 小时前
【GESP】C++五级练习题 luogu-P3353 在你窗外闪耀的星星
开发语言·c++·算法
Howrun7774 小时前
C++ 类间交互
开发语言·c++