C++11智能指针
前言
最近一段时间看代码,里面用到了C++的智能指针,发现自己竟然看不懂代码在表达什么意思,所以专门抽个时间恶补一下自己这方面欠缺的知识。
参考书籍《深入应用C++11:代码优化与工程级应用》
智能指针
C++11提供了3种智能指针:
- std::shared_ptr、
- std::uniqe_ptr
- std::weak_ptr
使用时需要引用头文件#include <memory>
std::shared_ptr
std::share_ptr 使用引用计数,每一个shared_ptr的拷贝都指向相同的内存,最后一个shared_ptr析构的时候,内存才会释放。
1 share_ptr的基本用法
智能指针初始化以及赋值
不允许将普通指针赋值给智能指针,因为智能指针是一个类,而普通指针是一个值
对于一个没有初始化的指针可以使用Reset来完成初始化。
- 智能指针通过重载bool类型操作符,所以可以直接使用智能指针来判断是否为空
2 获取原始指针
使用p.get()
可以获取智能指针的原始指针,cout也可以直接输出原始指针。
普通指针可以直接等于原始指针get()到的指针数据
3,指定删除器
智能指针初始化可以指定删除器
可以使用lambda表达式简化删除器的写法
当使用智能指针管理数组的时候,需要使用删除器,因为std::share_ptr不支持数组对象的释放
也可以使用默认的删除器,std::default_delete
在VC++中没法使用default_delete
std::shared_ptr<int> p(new int[10], std::default_delete<int[]>);
4. 使用shared_ptr注意事项
不要用一个原始指针初始化多个shared_ptr,原因在于,会造成二次销毁,如下所示:
使用VC++2015测试发现,使用原始指针创建多个智能指针,会产生错误
!
使用智能指针初始化多个智能指针就不会存在问题,因为智能指针全部会纳入计数体系不要在函数实参中创建shared_ptr。因为C++的函数参数的计算顺序在不同的编译器下是不同的。正确的做法是先创建好,然后再传入
//错误示范
function(shared_ptr<int>(new int), g());
通过shared_from_this()返回this指针。
文中sp1返回的this指针作为裸指针使用,sp2拿到指针后成为与sp1无关的智能指针。两个智能指针在声明周期结束后,都会进行析构,结果形成了重复析构的操作
智能指针不能直接返回this指针,需要通过派生std::enable_shared_from_this
类,通过其方法shared_frome_this()
来返回智能指针。避免循环使用。智能指针的最大缺陷就是循环引用,循环引用会导致两个指针都不会被析构。
当两个智能指针相互引用对方时,由于计数都为2,所以在结束时,没有达到析构的条件,所以都不会析构
std::unique_ptr
独占的智能指针,它不允许其他职能指针共享其内部的指针,不允许通过赋值,将一个unique_ptr赋值给另外一个unique_ptr
unique_ptr<int> myPtr(new int(1));
//下面的代码是错误的,无法通过=进行复制
unique_ptr<int> myPtr2 = myPtr;
unique_ptr虽然不可以复制,但是可以转移,通过std::move来转移到其他的unique_ptr
可以看到unique_ptr通过move的方式,转移了指针的内容
//unique_ptr只可以move不可以复制
unique_ptr<MyType> other_p2 = other_p;
关于shared_ptr和uunique_ptr的使用场景,要根据实际应用来选择,如果只希望有一个智能指针管理资源或者管理数组就用unique_ptr,如果希望有多个只能指针管理同一个资源,就用shared_ptr
std::unique_ptr可以释放数组吗?
unique_ptr
支持数组的释放,而shared_ptr
不支持数组的释放
weak_ptr弱引用智能指针
- 弱引用指针weak_ptr是用来监视shared_ptr的。主要是为了监视shared_ptr的声明周期。
- 因为weak_ptr没有重载操作符*和->所以不能操作资源。
- 它的构造不会增加引用计数,它的析构也不会减少引用计数,只是用来监测shared_ptr中管理的资源是否存在。
- weak_ptr还可以用来返回this指针和解决循环引用的问题
weak_ptr基本用法
- 通过
use_cout()
来获取当前观察资源的引用计数
- 通过
expired()
来获取是否有效
- 通过
lock
方法来获取所监视的shared_ptr
,
- lock之后可以访问指针的内容
- weak_ptr可以通过直接赋值的方式来进行监视
通过智能指针管理第三方库分配的内存
智能指针适合于调用第三方接口库时使用,由于第三方库返回指针一般都是原始指针,所以使用智能指针可以在执行出错的情况下调用
void* p = GetHandle()->Create();
std::shared_ptr<void> sp(p, [this](void*p){GetHandle()->Release(p);});
总结
- share_ptr的复制会增加计数,每次复制都会增加,只有最后一次释放的时候,才是真正的delete指针。
- shared_ptr和uniqi_ptr如何选择:如果只有一个只能指针管理资源或者管理数组,可以使用uniq_ptr.如果希望多个智能指针管理同一个资源,可以用shared_ptr
- weak_ptr是shared_ptr的助手,只是监视shared_ptr管理的资源是否被释放,本身不使用指针进行资源管理。用于解决share_ptr的循环引用和返回this指针的问题。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步