Is there a way to increase the efficiency of shared_ptr by storing the reference count inside the controlled object?

前端 未结 4 1909
有刺的猬
有刺的猬 2021-01-20 19:15

This is becoming a common pattern in my code, for when I need to manage an object that needs to be noncopyable because either A. it is \"heavy\" or B. it is an operating sys

相关标签:
4条回答
  • 2021-01-20 19:44

    A partial solution is to use make_shared to create your shared_ptrs. For example,

    auto my_thing = std::make_shared<Thing>();
    

    instead of

    auto my_thing = std::shared_ptr<Thing>(new Thing);
    

    It's still non-intrusive, so nothing else needs to change. Good implementations of make_shared combine the memory allocation for the reference count and the object itself. That saves a memory allocation and keeps the count close to the object for better locality. It's not quite as efficient as something like boost:intrusive_ptr, but it's worth considering.

    0 讨论(0)
  • 2021-01-20 19:44

    you can save some overhead by simply getting rid of the two classes and having just one and typedefing a shared ptr to it - this is the idom i use all the time

     class Resource
     {
          ...
     };
     typedef boost::shared_ptr<Resource> ResourcePtr;
    
    0 讨论(0)
  • 2021-01-20 20:01

    If you want to reduce the overhead of distinct memory allocations for your object and the reference counter, you could try to use make_shared. That's what its for.

    0 讨论(0)
  • 2021-01-20 20:02

    Use a boost::intrusive_ptr which is designed to work on a class with an embedded reference count.

    Non-tested example based on example here:

    class Resource; 
    
    class Implementation : public boost::noncopyable 
    { 
        friend class Resource;
        HANDLE someData;
        int refCount; // The reference count.
        Implementation(HANDLE input) : someData(input) { refCount = 0; }; 
        void SomeMethodThatActsOnHandle() { 
            //Do stuff 
        }; 
    public: 
        ~Implementation() { FreeHandle(someData) }; 
    };
    
    intrusive_ptr_add_ref(Implementation* imp) { imp->refCount++; }
    intrusive_ptr_release(Implementation* imp) { if(--imp->refCount) == 0) delete imp; }
    
    class Resource 
    { 
        boost::intrusive_ptr<Implementation> impl; 
    public: 
        Resource(int argA) explicit { 
            HANDLE handle =  
                SomeLegacyCApiThatMakesSomething(argA); 
            if (handle == INVALID_HANDLE_VALUE) 
                throw SomeTypeOfException(); 
            impl.reset(new Implementation(handle)); 
        }; 
        void SomeMethodThatActsOnTheResource() { 
            impl->SomeMethodThatActsOnTheHandle(); 
        }; 
    }; 
    
    0 讨论(0)
提交回复
热议问题