智能指针
- 智能指针
- 自己实现智能指针
- 不带引用计数的智能指针
- 带引用计数的智能指针
- 智能指针的交叉引用(循环引用)问题
- 多线程访问共享对象问题
- 自定义删除器
智能指针的介绍
为什么需要智能指针?
- 忘记释放资源,导致资源泄露(常发生内存泄漏问题)
- 同一资源释放多次,导致释放野指针,程序崩溃
- 明明代码的后面写了释放资源的代码,但是由于程序逻辑满足条件,从中间return掉了,导致释放资源的代码未被执行到
- 代码运行过程中发生异常,随着异常栈展开,导致释放资源的代码未被执行
auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被c++11弃用。所以我只说后3个。
- shared_ptr 采用引用计数的智能指针。 如果你想要将一个原始指针分配给多个所有者(例如,从容器返回了指针副本又想保留原始指针时),请使用该指针。 直至所有 shared_ptr 所有者超出了范围或放弃所有权,才会删除原始指针。 大小为两个指针;一个用于对象,另一个用于包含引用计数的共享控制块。 头文件:。 有关详细信息,请参阅 如何:创建和使用 Shared_ptr 实例 和 shared_ptr 类。
- unique_ptr 只允许基础指针的一个所有者。 除非你确信需要 shared_ptr,否则请将该指针用作 POCO 的默认选项。 可以移到新所有者,但不会复制或共享。 替换已弃用的 auto_ptr。 与 boost::scoped_ptr 比较。 unique_ptr 很小且高效;大小是一个指针,它支持用于从 c + + 标准库集合快速插入和检索的右值引用。 头文件:。 有关详细信息,请参阅 如何:创建和使用 Unique_ptr 实例 和 unique_ptr 类。
- 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;
}
};