建设网站的公司济南兴田德润o简介图片,东莞公众号开发公司,wordpress+音乐网,智慧景区网站服务建设智能指针
本人不才#xff0c;只能将智能指针介绍一下#xff0c;无法结合线程进行深入探索
介绍及作用
在异常产生进行跳转时#xff0c;通过栈帧回收进行内存释放#xff0c;防止内存泄漏 基于RAII思想可以创建出只能指针 RAII(Resource Acquisition Is Initializatio…智能指针
本人不才只能将智能指针介绍一下无法结合线程进行深入探索
介绍及作用
在异常产生进行跳转时通过栈帧回收进行内存释放防止内存泄漏 基于RAII思想可以创建出只能指针 RAII(Resource Acquisition Is Initialization)——是一种利用对象控制空间生命周期的技术 这种技术好处就在于可以自动化的释放资源 智能指针——使用如指针支持-和**针对内置数据类型-针对自定义数据类型 先介绍一个对象管理一份资源
auto_ptr templateclass Tclass auto_ptr{// auto_ptr 会产生指针悬空的情况,在进行解引用的时候很危险public:auto_ptr(T* pnullptr) :_ptr(p) {}~auto_ptr(){puts(~auto_ptr());delete _ptr;}auto_ptr(auto_ptrT p){_ptr p._ptr;p._ptr nullptr;}auto_ptrT operator(auto_ptrT p){// 因为是一个对象管理一份资源,比较的时候也可以使用this!pif (_ptr ! p._ptr){if (_ptr) delete _ptr;_ptr p._ptr;p._ptr nullptr;}return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};auto_ptr会在赋值的时候将资源进行转移并将自己置为nullptr从而造成指针悬空的问题 unique_ptr templateclass Tclass unique_ptr{// 在auto_ptr的基础上进行优化,防拷贝public:unique_ptr(T* p nullptr) :_ptr(p) {}~unique_ptr(){puts(~auto_ptr());delete _ptr;}unique_ptr(const unique_ptrT p) delete;unique_ptr operator(const unique_ptrT p) delete;T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:// unique_ptr(const unique_ptrT p);// unique_ptr operator(const unique_ptrT p);T* _ptr;};只是为了解决拷贝带来的指针悬空的问题——禁用拷贝构造和赋值重载 有两种方式达到禁用拷贝构造和赋值重载 将拷贝构造和赋值重载定义成private由于C11扩展了delete的功能可以在public中对两个函数使用delete关键字修饰 多个指针同时享有一份资源
shared_ptr 使用一个计数指针进行计数 我的代码写成这个样子是因为考虑到可能只声明指针但是没有赋值的情况所以就需要对指针位nullptr的情况进行特殊判断 struct ListNode
{int val;bit::shared_ptrListNode next;bit::shared_ptrListNode prev;~ListNode(){cout ~ListNode() endl;}
};templateclass Tclass shared_ptr {// 删除器就是为了解决:释放数组,不是new出来的指针public:shared_ptr(T* p nullptr) :_ptr(p), _count(new int(0)) {}templateclass Dshared_ptr(T* p,D del):_ptr(p),_count(new int(1)),_del(del){if (p) (*_count);}~shared_ptr(){if (_ptr){//printf(~shared_ptr() - %p\n, _ptr);if (--(*_count) 0){delete _count;}delete _ptr;}if (_ptr nullptr) delete _count;}shared_ptr(const shared_ptrT p){if (_ptr _ptr ! p._ptr){if (--(*_count) 0) _count p._count;(*_count);_ptr p._ptr;}else{// nullptr / 有值相等_ptr p._ptr;_count p._count;//*_count; // 优先级大于*,最好不要写这种代码(*_count);}}shared_ptr operator(const shared_ptrT p){if (_ptr _ptr ! p._ptr){if (--(*_count) 0) _count p._count;(*_count);_ptr p._ptr;}else{// nullptr / 有值相等_ptr p._ptr;_count p._count;(*_count);}return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}int use_count() const {return *_count;}T* get() const{return _ptr;}private:T* _ptr;int* _count;// 引入计数指针functionvoid(T*) _del [](T* p) {delete p; };};这里会产生循环引用的问题 为了解决这个问题有了weak_ptr weak_ptr
weak_ptr只进行引用不进行计数
struct ListNode
{int val;bit::weak_ptrListNode next;bit::weak_ptrListNode prev;~ListNode(){cout ~ListNode() endl;}
};templateclass Tclass weak_ptr{// 不增加引用计数public:weak_ptr() :_ptr(nullptr) {}~weak_ptr(){//printf(~shared_ptr() - %p\n, _ptr);}weak_ptr(const shared_ptrT p){_ptr p.get();}weak_ptr operator(const shared_ptrT p){_ptr p.get();return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};使用包装器进行释放
这里还有一个问题——如何根据空间开的个数进行释放呢数组和指针释放的方式是不一样的 也就是在share_ptr看不懂的版本
templateclass T
struct Del
{void operator()(T* ptr){delete[] ptr;}
};templateclass Tclass shared_ptr {// 删除器就是为了解决:释放数组,不是new出来的指针public:shared_ptr(T* p nullptr) :_ptr(p), _count(new int(0)) {}templateclass Dshared_ptr(T* p,D del):_ptr(p),_count(new int(1)),_del(del){if (p) (*_count);}~shared_ptr(){if (_ptr){//printf(~shared_ptr() - %p\n, _ptr);if (--(*_count) 0){delete _count;}delete _ptr;}if (_ptr nullptr) delete _count;}shared_ptr(const shared_ptrT p){if (_ptr _ptr ! p._ptr){if (--(*_count) 0) _count p._count;(*_count);_ptr p._ptr;}else{// nullptr / 有值相等_ptr p._ptr;_count p._count;//*_count; // 优先级大于*,最好不要写这种代码(*_count);}}shared_ptr operator(const shared_ptrT p){if (_ptr _ptr ! p._ptr){if (--(*_count) 0) _count p._count;(*_count);_ptr p._ptr;}else{// nullptr / 有值相等_ptr p._ptr;_count p._count;(*_count);}return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}int use_count() const {return *_count;}T* get() const{return _ptr;}private:T* _ptr;int* _count;// 引入计数指针functionvoid(T*) _del [](T* p) {delete p; };};仿函数函数指针lambda可以使用包装器——不论使用哪一种实现的目的就是为了释放数组 他的类型一定是void(*T) 为什么需要在声明的时候就给默认到lambda——如果在这个指针是拷贝构造生成的那还得进行包装器拷贝同样在赋值重载的地方也需要同样的操作还不如声明的时候给默认值