• [5] 智能指针boost::shared_ptr


    【1】boost::shared_ptr简介

    boost::shared_ptr属于boost库,定义在namespace boost中,包含头文件#include<boost/shared_ptr.hpp>便可以使用。

    上篇《智能指针boost::scoped_ptr》中我们看到boost::scoped_ptr独享所有权,不允许赋值、拷贝。

    而boost::shared_ptr是专门用于共享所有权的,由于要共享所有权,其在内部使用了引用计数机制。同时也就意味着支持赋值和拷贝。

    boost::shared_ptr也是用于管理单个堆内存对象的。

    【2】boost::shared_ptr详解

    应用实例代码如下:

     1 #include <iostream>
     2 #include <boost/shared_ptr.hpp>
     3 
     4 class Int
     5 {
     6 public:
     7     Int(int nValue = 0) 
     8     {
     9         m_nValue = nValue;
    10         std::cout << "Constructor: " << m_nValue << std::endl; 
    11     }
    12     ~Int() 
    13     {
    14         std::cout << "Destructor: " << m_nValue << std::endl;
    15     }
    16     void PrintValue()
    17     {
    18         std::cout << "PrintValue: " <<m_nValue<< std::endl;
    19     }
    20     void SetValue(int nSetValue)
    21     {
    22         m_nValue = nSetValue;
    23     }
    24 
    25 private:
    26     int m_nValue;
    27 };
    28 
    29 void TestShared_Ptr(boost::shared_ptr<Int> spInt) 
    30 {  // 注意:无需使用 reference (或 const reference)
    31     spInt->PrintValue();
    32     std::cout << "TestShared_Ptr UseCount: " << spInt.use_count() << std::endl;
    33 }
    34 
    35 void TestShared_Ptr2() 
    36 {
    37     boost::shared_ptr<Int> spInt(new Int(10));
    38     if (spInt.get())
    39     {
    40         spInt->PrintValue();    
    41         spInt.get()->SetValue(20);
    42         spInt->PrintValue();    
    43         (*spInt).SetValue(30);
    44         spInt->PrintValue();
    45     }
    46 
    47     std::cout << "TestShared_Ptr2 UseCount: " << spInt.use_count() << std::endl;
    48     TestShared_Ptr(spInt);
    49     std::cout << "TestShared_Ptr2 UseCount: " << spInt.use_count() << std::endl;
    50 
    51     //spInt.release();// 编译 error: 同样,shared_ptr也没有release函数
    52 }
    53 
    54 //执行结果如下:
    55 /*
    56 Constructor: 10
    57 PrintValue: 10
    58 PrintValue: 20
    59 PrintValue: 30
    60 TestShared_Ptr2 UseCount: 1
    61 PrintValue: 30
    62 TestShared_Ptr UseCount: 2
    63 TestShared_Ptr2 UseCount: 1
    64 Destructor: 30
    65 */

    实例可见,boost::shared_ptr也可以很方便的使用。并且没有release()函数。

    关键的一点,boost::shared_ptr内部维护了一个引用计数,由此可以支持复制、参数传递等。

    boost::shared_ptr提供了一个函数use_count(),此函数返回 boost::shared_ptr内部的引用计数。

    查看执行结果,我们可以看到在 TestShared_Ptr2函数中,引用计数为1,传递参数后(此处进行了一次复制),

    在函数TestShared_Ptr内部,引用计数为2,在TestShared_Ptr返回后,引用计数又降低为1。

    另外,由TestShared_Ptr2内创建智能指针对象,到函数结束再析构智能指针对象,确保释放掉内存资源。

    当我们需要使用一个共享对象的时候,boost::shared_ptr是最佳选择。

    此例也正体现了boost::shared_ptr是支持值语义,提供引用计数机制及RAII支持的智能指针。

    【3】boost::shared_ptr总结

    boost::shared_ptr的管理机制其实并不复杂,就是对所管理的对象进行了引用计数。

    当新增一个boost::shared_ptr对该对象进行管理时,就将该对象的引用计数加一;

    减少一个boost::shared_ptr对该对象进行管理时,就将该对象的引用计数减一;

    如果该对象的引用计数为0的时候,说明没有任何指针对其管理,才调用delete释放其所占的内存。

     

    boost::shared_ptr并不是绝对安全,下面几条规则能使我们更加安全的使用boost::shared_ptr:

    1.避免对shared_ptr所管理的对象的直接内存管理操作,以免造成该对象的重释放

    2.shared_ptr并不能对循环引用的对象内存自动管理(这点是其它各种引用计数管理内存方式的通病)。

    3.不要构造一个临时的shared_ptr作为函数的参数。

    如下列代码则可能导致内存泄漏:

     1 void test() 
     2 {     
     3     fun(boost::shared_ptr<Int>(new Int()).g());
     4 } 
     5 //正确的用法为: 
     6 void test() 
     7 {     
     8     boost::shared_ptr<Int> spInt(new Int());     
     9     fun(spInt.g()); 
    10 }

    当函数g()抛异常的时候就会泄露了,这个是boost文档上特地注明的标准bad Practices。

     

    Good Good Study, Day Day Up.

    顺序  选择  循环  总结

  • 相关阅读:
    flutter开发No toolchains found in the NDK toolchains folder for ABI with prefix: armlinuxandroideabi错误的解决方法
    android开发 [CXX1104] NDK from ndk.dir at androidSdk\ndk\21.1.6352462 had version [21.1.6352462] which disagrees with android.ndkVersion [21.0.6113669]错误的解决方法
    android开发如何让Parcelable的使用和Serializable一样简单的解决方法
    flutter开发Build failed due to use of deprecated Android v1 embedding错误的解决方法
    android开发kotlin编译出错Module was compiled with an incompatible version of Kotlin
    android开发让App永不闪退,永不crash的解决方法
    android开发突破Android P及以上反射调用隐藏API限制的解决方法
    flutter开发The ADB at "androidSdk\platformtools\adb.exe" is too old; please install version 1.0.39 or later.错误的解决方法
    Android开发Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.错误的解决方法
    android开发以调试模式启动app方便调试启动时的代码
  • 原文地址:https://www.cnblogs.com/Braveliu/p/3295742.html
Copyright © 2020-2023  润新知