• [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.

    顺序  选择  循环  总结

  • 相关阅读:
    一行代码搞定图片缩放、旋转、加水印
    如何学习 Webpack
    Webpack 概念
    Webpack 入门
    asp.net core教程 (一)
    asp.net core教程 (二)
    ap.net core 教程(三)
    Grafana 安装配置
    zabbix-3.0.x LTS源码安装配置
    MariaDB Security
  • 原文地址:https://www.cnblogs.com/Braveliu/p/3295742.html
Copyright © 2020-2023  润新知