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注意事项

  1. 不要用一个原始指针初始化多个shared_ptr,原因在于,会造成二次销毁,如下所示:

    使用VC++2015测试发现,使用原始指针创建多个智能指针,会产生错误
    !
    使用智能指针初始化多个智能指针就不会存在问题,因为智能指针全部会纳入计数体系

  2. 不要在函数实参中创建shared_ptr。因为C++的函数参数的计算顺序在不同的编译器下是不同的。正确的做法是先创建好,然后再传入

//错误示范
function(shared_ptr<int>(new int), g());
  1. 通过shared_from_this()返回this指针。

    文中sp1返回的this指针作为裸指针使用,sp2拿到指针后成为与sp1无关的智能指针。两个智能指针在声明周期结束后,都会进行析构,结果形成了重复析构的操作

    智能指针不能直接返回this指针,需要通过派生std::enable_shared_from_this类,通过其方法shared_frome_this()来返回智能指针。

  2. 避免循环使用。智能指针的最大缺陷就是循环引用,循环引用会导致两个指针都不会被析构。

    当两个智能指针相互引用对方时,由于计数都为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指针的问题。




posted @ 2018-06-05 14:19  小黑的守望  阅读(1007)  评论(0编辑  收藏  举报