1. 智能指针
  2. 自己实现智能指针
  3. 不带引用计数的智能指针
  4. 带引用计数的智能指针
  5. 智能指针的交叉引用(循环引用)问题
  6. 多线程访问共享对象问题
  7. 自定义删除器

智能指针的介绍

为什么需要智能指针?

  1. 忘记释放资源,导致资源泄露(常发生内存泄漏问题)
  2. 同一资源释放多次,导致释放野指针,程序崩溃
  3. 明明代码的后面写了释放资源的代码,但是由于程序逻辑满足条件,从中间return掉了,导致释放资源的代码未被执行到
  4. 代码运行过程中发生异常,随着异常栈展开,导致释放资源的代码未被执行

auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被c++11弃用。所以我只说后3个。

  1. shared_ptr 采用引用计数的智能指针。 如果你想要将一个原始指针分配给多个所有者(例如,从容器返回了指针副本又想保留原始指针时),请使用该指针。 直至所有 shared_ptr 所有者超出了范围或放弃所有权,才会删除原始指针。 大小为两个指针;一个用于对象,另一个用于包含引用计数的共享控制块。 头文件:。 有关详细信息,请参阅 如何:创建和使用 Shared_ptr 实例 和 shared_ptr 类。
  2. unique_ptr 只允许基础指针的一个所有者。 除非你确信需要 shared_ptr,否则请将该指针用作 POCO 的默认选项。 可以移到新所有者,但不会复制或共享。 替换已弃用的 auto_ptr。 与 boost::scoped_ptr 比较。 unique_ptr 很小且高效;大小是一个指针,它支持用于从 c + + 标准库集合快速插入和检索的右值引用。 头文件:。 有关详细信息,请参阅 如何:创建和使用 Unique_ptr 实例 和 unique_ptr 类。
  3. weak_ptr 结合 shared_ptr 使用的特例智能指针。 weak_ptr 提供对一个或多个 shared_ptr 实例拥有的对象的访问,但不参与引用计数。 如果你想要观察某个对象但不需要其保持活动状态,请使用该实例。 在某些情况下,需要断开 shared_ptr 实例间的循环引用。 头文件:。 有关详细信息,请参阅 如何:创建和使用 Weak_ptr 实例 和 weak_ptr 类。

自己实现智能指针

智能指针 :保证能做到资源的自动释放

利用栈上的对象出作用域自动析构的特征,来做到自动释放资源

#include<iostream>
using namespace std;

template<typename T>
class smartPtr{
public:
    smartPtr(T* x = NULL) : data(x){cout<<"smartPtr()"<<endl;}
    ~smartPtr(){delete data;}
    T& operator*() {return *data; }
    T* operator->() {return data};
private:
    T* data;
};

signed main(){
    smartPtr<int> a(new int);
    *a = 10;
    cout<<*a<<endl;
}

不带引用计数的智能指针

解决多个智能指针浅拷贝时多次析构同一个指针造成的内存问题

auto_ptr

(不推荐 , 底层一坨) 对转移对象的所有权

附auto_ptr拷贝构造的代码

//这是拷贝构造
auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }

//release方法
release() throw()
      {
	element_type* __tmp = _M_ptr;
	_M_ptr = 0;
	return __tmp;
      }

即拷贝构造时,会先删除被拷贝的指针,将原来的指针地址绑定到新的auto_ptr上,此时使用原来的ptr1就会寄寄

能不能在容器中使用auto_ptr ?

不行滴,容器中所有关于构造的方法都失效了

scoped_ptr

scoped_ptr强制删除了拷贝构造跟赋值运算符重载

scoped_ptr(const scoped_ptr<T>&) = delete;
scoped_ptr<T> &operate=(const scoped_ptr<T>&) = deleted;

scoped_ptr(const scoped_ptr<T>&&);
scoped_ptr<T> &operate=(const scoped_ptr<T>&&);

unique_ptr

推荐使用这个

unique_ptr(const unique_ptr&) = delete;
unique_ptr &operate=(const unique_ptr&) = deleted;

template<typename T>
    unique_ptr<T> getSmartPtr(T t){
        return unique_ptr<T>(new T(t));
    }

signed main(){
    unique_ptr<int> a = getSmartPtr(10);
    unique_ptr<int> b(move(a));
    cout<<*b<<endl;
}

用了move,代表用户已经知道了此时a已经不持有资源了,a已经把所有的资源交给了b

带引用计数的智能指针

多个智能指针可以管理同一个资源

带引用计数:给每一个对象资源,匹配一个引用计数

智能指针 -> 资源 -> 引用+1

智能指针 -> 不使用资源 -> 引用-1 , if 引用 = 0 ,析构 ,else 不析构

本身就线程安全(可以直接用在多线程环境下)

弱智能指针 观察 弱智能指针

share_ptr

强智能指针,可以改变资源的引用计数

强智能指针的循环引用(交叉引用)是什么问题?什么结果?怎么解决?

造成new出来的资源无法释放(资源泄露问题)

解决方案:

定义的时候使用强智能指针, 引用的时候使用弱智能指针

weak_ptr

弱智能指针,不会改变资源的引用计数

只提供对强智能只针对观察,不提供对强指针资源的访问

如果要使用资源的话,需要提高这个方式:

weak_ptr<A> t;
share_ptr<int> ps = t.lock();
if(ps != nullptr){
	ps->ATest();
}

自定义删除器

智能指针的删除器;deletor

智能指针:能够保证资源绝对的释放 delete ptr;

~unique_queue(){ 函数对象的调用 deletor(ptr); }

默认deletor (即默认是delete)

class Deletor{
    public:
    void operator() (T *ptr){
        delete ptr;
    }
};
文章作者: cosh
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 cosh'blog
C++
喜欢就支持一下吧