手撕简易版的智能指针

目录

一、智能指针的通用模板

二、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;};
    };
相关推荐
南境十里·墨染春水6 分钟前
C++笔记 STL——set
开发语言·c++·笔记
dgaf19 分钟前
DX12 快速教程(17) —— 立体图标与合并渲染
c语言·c++·3d·图形渲染·d3d12
charlie1145141913 小时前
通用GUI编程技术——图形渲染实战(三十八)——顶点缓冲与输入布局:GPU的第一个三角形
开发语言·c++·学习·图形渲染·win32
用户805533698033 小时前
现代Qt开发教程(新手篇)1.10——进程
c++·qt
海参崴-3 小时前
C++ STL篇 AVL树的模拟实现
开发语言·c++
汉克老师3 小时前
GESP2025年6月认证C++五级( 第二部分判断题(1-10))
c++·贪心算法·分治算法·线性筛法·gesp5级·gesp五级
6Hzlia3 小时前
【Hot 100 刷题计划】 LeetCode 15. 三数之和 | C++ 排序+双指针
c++·算法·leetcode
vegetablesssss4 小时前
VTK切割图
c++·qt·vtk
CN-Dust4 小时前
【C++】for循环例题专题
java·c++·算法
IOT那些事儿4 小时前
Qt5 VSCode调试
c++·vscode·mingw·qt5