zoukankan      html  css  js  c++  java
  • 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指针的问题。




  • 相关阅读:
    php数组函数-array_push()
    php数组函数-array_pop()
    php数组函数-array_pad()
    php数组函数-array_merge()
    php数组函数-array_map()
    php数组函数-array_keys()
    php数组函数-array_key_exists()
    php数组函数-array_intersect()
    php数组函数-array_flip()
    php数组函数-array_filter()
  • 原文地址:https://www.cnblogs.com/EltonLiang/p/9139566.html
Copyright © 2011-2022 走看看