美文网首页
boost::intrusive_ptr的用法

boost::intrusive_ptr的用法

作者: JasonLiThirty | 来源:发表于2020-02-13 19:22 被阅读0次

    视频教程:https://www.bilibili.com/video/av88980020/

    boost::intrusive_ptr和shared_ptr的区别

    • shared_ptr最大的陷阱就是用同一个裸指针创建了多个shared_ptr,这会导致这些shared_ptr析构时,因为每个shared_ptr都有自己引用计数,导致这个裸指针多次销毁
    • 所以不能用一个裸指针来创建多个shared_ptr,但却可以来创建多个intrusive_ptr,因为所使用的对象通过继承包含引用计数功能的基类(将引用计数作为对象的内部成员变量,大家共用一个计数器,就不会出现每个对象里都有自己的计数问题。
    • intrusive_ptr是“侵入式”的,所以它所指向的对象,必须继承包含引用计数功能的基类;而shared_ptr不是“侵入式”的,可指向任何类型的对象。
    • intrusive_ptr用在创建的对象需要传递的时候(例如总线传递等)

    boost::intrusive_ptr的使用

    #include <boost/intrusive_ptr.hpp>
    
    • “侵入式”的引用计数智能指针,实际不提供引用计数功能,要求被存储的对象类自己实现引用计数功能
    • 对象类需要提供intrusive_ptr_add_ref和intrusive_ptr_release友元函数接口供boost::intrusive_ptr调用来间接管理引用计数
    • 所以,首先需要实现一个基类来定义上述两个函数来提供引用计数功能,然后再派生出子类进行业务处理
    • intrusive_ptr的构造函数和reset()里有一个add_ref参数,表示是否增加引用计数,如果add_ref=false, 那么intrusive_ptr就是weak_ptr。
    • boost库里提供了一个辅助类intrusive_ref_counter,用来实现引用计数的工作,在头文件<boost/smart_ptr/intrusive_ref_counter>里

    boost::intrusive_ptr的例子

    • 建立一个提供引用计数功能的基类
    #ifndef REFERENCE_COUNTER_H
    #define REFERENCE_COUNTER_H
    
    #include <assert.h>
    #include <atomic>
    #include <iostream>
    
    class ReferenceCounter
    {
    public:
        friend void intrusive_ptr_add_ref(ReferenceCounter *p)
        {
            std::cout << "Call intrusive_ptr_add_ref" << std::endl;
            assert(p);
            assert(p->ref_count >= 0);
            ++p->ref_count;
        }
    
        friend void intrusive_ptr_release(ReferenceCounter *p)
        {
            std::cout << "Call intrusive_ptr_release" << std::endl;
            assert(p);
            assert(p->ref_count > 0);
            if (--p->ref_count == 0)
            {
                delete p;
            }
        }
    
        ReferenceCounter() :ref_count(0)
        {
            std::cout << "Reference Counter Constructor" << std::endl;
        }
    
        ReferenceCounter(const ReferenceCounter  &other)
        {
            std::cout << "Reference Counter Copy Constructor" << std::endl;
        }
    
        ReferenceCounter& operator=(const ReferenceCounter &other)
        {
            std::cout << "Reference Counter Assignment Operator" << std::endl;
        }
        
        ~ReferenceCounter() 
        {
            std::cout << "Reference Counter Destructor" << std::endl;
        };
    
        int RefCount()
        {
            return ref_count;
        }
    
    private:
        std::atomic_int ref_count;
    };
    #endif
    
    • 建立一个具体功能类
    #ifndef PROCESS_DATA_H
    #define PROCESS_DATA_H
    #include "ReferenceCounter.h"
    #include<string>
    #include<iostream>
    
    class ProcessData : public ReferenceCounter
    {
    public:
        ProcessData(int id, std::string info) :m_id(id), m_info(info) 
        {
            std::cout << "Process Data Constructor" << std::endl;
        }
    
        ProcessData(const ProcessData &other)
        {
            std::cout << "Process Data Copy Constructor" << std::endl;
            m_id = other.m_id;
            m_info = other.m_info;
        }
    
        const ProcessData operator=(const ProcessData &other)
        {
            std::cout << "Process Data Assignment Operator" << std::endl;
            m_id = other.m_id;
            m_info = other.m_info;
        }
    
        ~ProcessData()
        {
            std::cout << "Process Data Destructor" << std::endl;
        }
    
    private:
        int m_id;
        std::string m_info;
    };
    
    #endif 
    
    • boost::intrusive的使用
    #include "ProcessData.h"
    #include <boost/intrusive_ptr.hpp>
    
    
    int main()
    {
        boost::intrusive_ptr<ProcessData> ptr(new ProcessData(1, "a"));
        std::cout << "******************"<< std::endl;
        std::cout << "ref_count = " << ptr->RefCount() << std::endl;
        std::cout << "******************" << std::endl;
        {
            boost::intrusive_ptr<ProcessData> ptrCopy(ptr.get());
            std::cout << "ref_count after copy constructed = " << ptrCopy->RefCount() << std::endl;
        }
    
        std::cout << "******************" << std::endl;
        std::cout << "ref_count = " << ptr->RefCount() << std::endl;
        std::cout << "******************" << std::endl;
    
        {
            boost::intrusive_ptr<ProcessData> ptrAssignment = ptr;
            std::cout << "ref_count after assignment = " << ptrAssignment->RefCount() << std::endl;
        }
    
        std::cout << "******************" << std::endl;
        std::cout << "ref_count = " << ptr->RefCount() << std::endl;
        std::cout << "******************" << std::endl;
    
        {
            boost::intrusive_ptr<ProcessData> ptrWeak(ptr.get(), false);
            std::cout << "ref_count after construct weak_ptr = " << ptrWeak->RefCount() << std::endl;
        }
    
        std::cout << "******************" << std::endl;
        std::cout << "ref_count = " << ptr->RefCount() << std::endl;
        std::cout << "******************" << std::endl;
        
        system("pause");
        return 0;
    }
    
    //output
    Reference Counter Constructor
    Process Data Constructor
    Call intrusive_ptr_add_ref
    ******************
    ref_count = 1
    ******************
    Call intrusive_ptr_add_ref
    ref_count after copy constructed = 2
    Call intrusive_ptr_release
    ******************
    ref_count = 1
    ******************
    Call intrusive_ptr_add_ref
    ref_count after assignment = 2
    Call intrusive_ptr_release
    ******************
    ref_count = 1
    ******************
    ref_count after construct weak_ptr = 1
    Call intrusive_ptr_release
    Reference Counter Destructor
    ******************
    ref_count = -572662307
    ******************
    

    相关文章

      网友评论

          本文标题:boost::intrusive_ptr的用法

          本文链接:https://www.haomeiwen.com/subject/ztblfhtx.html