Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8281677
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 8, 20262026-06-08T10:07:03+00:00 2026-06-08T10:07:03+00:00

I am trying to understand the underlying design of boost shared_ptr class. I want

  • 0

I am trying to understand the underlying design of boost shared_ptr class. I want to “port” it to fortran (don’t ask). One thing I understand is that the reference count is held by a shared_count class. This prompts me a question. I haven’t used C++ since a long time, and never used boost.

Suppose I allocate a single instance of a class X, then pass it to two different shared_ptr instances. From what I understand, each shared_ptr instance does not know anything about the other, hence both shared_ptr instances are referring to the same X instance, while keeping a refcount of 1. if one shared_ptr goes out of scope while the other doesn’t, the X object will be deleted (as the refcount drops to zero) and the remaining shared_ptr will have a dangling pointer. In order to keep the shared_ptr refcount, you have to create a shared_ptr from another shared_ptr.

Am I right ? If not, how can boost keep track of which shared_ptrs are referencing a class that knows nothing about the fact that is being referenced through shared_ptrs ?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-08T10:07:05+00:00Added an answer on June 8, 2026 at 10:07 am

    Basically you’re right. Your example will result in dangling pointer (note that there are some exceptions if you use boost::enable_shared_from_this as base class).

    Explanation

    Problem

    boost:shared_ptr and std::shared_ptr share the same idea: create a smart pointer with a reference count from a raw pointer. However, they also share the same problem that all smart pointer have: if you use the raw pointer in another smart pointer which isn’t associated to your other smart pointer, you’ll end with dangling pointers and multiple calls of delete:

    int * ptr = new int;
    {
        std::shared_ptr<int> shared1(ptr); // initialise a new ref_count = 1
        {
            std::shared_ptr<int> shared2(ptr);  // initialise a new ref_count = 1
        } // first call of delete, since shared2.use_count() == 0
    } // second call of delete, since shared1.use_count() == 0. ooops
    

    “Solution”

    After you created your first smart pointer S from a raw pointer p to an object O you should only use copy constructors with S, not with p, as long as O isn’t a derivate from std::enable_shared_from_this. boost has a somewhat equivalent of this, but mixing raw pointer and smart pointer is still a bad idea. Even better – don’t use raw pointer if you work with smart pointer:

    std::shared_ptr<int> ptr(new int);
    {
        std::shared_ptr<int> shared1(ptr); // ptr.use_count() == 2
        {
            std::shared_ptr<int> shared2(ptr);  // ptr.use_count()  = 3
        } // ptr.use_count()  = 2
    }  // ptr.use_count()  = 1
    

    Even better, don’t allocate the memory yourself but use std::make_shared or boost:make_shared:

    std::shared_ptr<int> ptr = std::make_shared<int>();
    {
        std::shared_ptr<int> shared1(ptr); // ptr.use_count() == 2
        {
            std::shared_ptr<int> shared2(ptr);  // ptr.use_count() == 3
        } // ptr.use_count() == 2
    }  // ptr.use_count() == 1
    

    Possible implementation

    The following implementation is very crude compared to the std::shared_ptr, as it doesn’t support std::weak_ptr and std::enable_shared_from_this. However, it should give you an overview how to handle a shared pointer:

    //!\brief Base clase for reference counter
    class reference_base{
        reference_base(const reference_base&);                            // not copyable
        reference_base& operator=(const reference_base &){return *this;}// not assignable    
    
    protected:
        size_t ref_count; //!< reference counter
        virtual void dispose() = 0; //!< pure virtual
    public:    
        //! initialize with a single reference count
        reference_base() : ref_count(1){}
    
        //! returns the current count of references
        size_t use_count() const{
            return ref_count;
        }
    
        //! increases the current count of references
        void increase(){
            ref_count++;
        }
    
        //! decreases the current count of references and dispose if the counter drops to zero
        void decrease(){
            if(--ref_count == 0)
                dispose();
        }
    };
    
    //! \brief Specialized version for pointer
    template <class T>
    class reference_base_ptr : public reference_base{
        typedef T* pointer_type;
    protected:
        //! uses delete to deallocate memory
        virtual void dispose(){
            delete ptr;
            ptr = 0;
        }
    public:
        reference_base_ptr(T * ptr) : ptr(ptr){}
        pointer_type ptr;
    };
    
    //! \brief Specialized version for arrays
    template <class T>
    class reference_base_range : public reference_base{
        typedef T* pointer_type;
    
    protected:
        virtual void dispose(){
            delete[] ptr;
            ptr = 0;
        }
    public:
        reference_base_range(T * ptr) : ptr(ptr){}
        pointer_type ptr;
    };
    
    /***********************************************************/
    
    //! base class for shared memory
    template <class T, class reference_base_type>
    class shared_memory{
        public:
            typedef T element_type;
    
            //! Standard constructor, points to null
            shared_memory() : reference_counter(new reference_base_type(0)){}
    
            //! Constructs the shared_memroy and creates a new reference_base
            template<class Y> shared_memory(Y * ptr){
                try{
                    reference_counter = new reference_base_type(ptr);
                }catch(std::bad_alloc &e){
                    delete ptr;
                    throw;
                }
            }
            //! Copies the shared_memory and increases the reference count
            shared_memory(const shared_memory & o) throw() : reference_counter(o.reference_counter){
                o.reference_counter->increase();
            }
    
            //! Copies the shared_memory of another pointer type and increases the reference count.
            //! Needs the same reference_base_type
            template<class Y> 
            shared_memory(const shared_memory<Y,reference_base_type> & o) throw() : reference_counter(o.reference_counter){
                reference_counter->increase();
            }
    
            //! Destroys the shared_memory object and deletes the reference_counter if this was the last
            //! reference.        
            ~shared_memory(){
                reference_counter->decrease();
                if(reference_counter->use_count() == 0)
                    delete reference_counter;
            }
    
            //! Returns the number of references
            size_t use_count() const{
                return reference_counter->use_count();
            }
    
            //! Returns a pointer to the refered memory
            T * get() const{
                return reference_counter->ptr;
            }
    
            //! Checks whether this object is unique
            bool unique() const{
                return use_count() == 1;
            }        
    
            //! Checks whehter this object is valid
            operator bool() const{
                return get() != 0;
            }
    
            //! Checks doesn't reference anythign
            bool empty() const{
                return get() == 0;
            }
    
            //! Assignment operator for derived classes
            template<class Y> 
            shared_memory& operator=(const shared_memory<Y,reference_base_type> & o){
                shared_memory<Y,reference_base_type> tmp(o);
                swap(tmp);
            }
    
            //! Assignment operator
            shared_memory& operator=(const shared_memory & o){
                shared_memory tmp(o);
                swap(tmp);
                return *this;
            }
    
            /** resets the ptr to NULL. If this was the last shared_memory object
            *   owning the referenced object, the object gets deleted.
            *   \sa ~shared_memory
            */
            void reset(){
                shared_memory tmp;
                swap(tmp);
            }
    
            /** releases the old object and takes a new one
            */
            template <class Y>
            void reset(Y * ptr){
                shared_memory tmp(ptr);
                swap(tmp);
            }        
    
            /** swaps the owned objects of two shared_memory objects.
            */
            void swap(shared_memory & r){
                reference_base_type * tmp = reference_counter;
                reference_counter = r.reference_counter;
                r.reference_counter = tmp;
            }
    
        protected:        
            reference_base_type * reference_counter;    //!< Actually reference counter and raw pointer
    };
    
    /***********************************************************/
    
    //! ptr (single object) specialization
    template <class T>
    class shared_ptr : public shared_memory<T,reference_base_ptr<T> >{
        typedef reference_base_ptr<T> reference_counter_type;
        typedef shared_memory<T,reference_counter_type> super;
        typedef T element_type;
    public:
        shared_ptr(){}
        template<class Y> shared_ptr(Y * ptr){
            try{
                super::reference_counter = new reference_counter_type(ptr);
            }catch(std::bad_alloc &e){
                //couldn't allocated memory for reference counter
                delete ptr; // prevent memory leak
                throw bad_alloc();
            }
        }
        element_type & operator*() const{
            return *(super::reference_counter->ptr);
        }
        element_type * operator->() const{
            return super::reference_counter->ptr;
        }
    };
    
    /***********************************************************/
    
    //! array (range) specialization
    template <class T>
    class shared_array : public shared_memory<T,reference_base_range<T> >{
        typedef reference_base_range<T> reference_counter_type;
        typedef shared_memory<T,reference_counter_type> super;
        typedef T element_type;
    
    public:
        shared_array(){}
        template<class Y> shared_array(Y * ptr){
            try{
                super::reference_counter = new reference_counter_type(ptr);
            }catch(std::bad_alloc &e){
                delete[] ptr;
                throw bad_alloc();
            }
        }
        element_type & operator[](int i) const{
            return *(super::reference_counter->ptr + i);
        }
    };
    

    See also:

    • std::shared_ptr
    • boost::shared_ptr, especially the section Best Practices
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Trying to implement a MSMQ-backed WCF PubSub. I understand that net.msmq is one-way; however
Im trying to understand how class generics work and this bit just doesnt make
I know how to use properties and I understand that they implicitly call underlying
Trying to understand radix sort for my data structures class. My teacher showed us
Trying to understand upcasting in Java. Recently observed strange behavior. Example: public class A
I am trying understand how multi queries work in mysqli. But I confess that
I am trying understand ViewModels deeper and I have read many articles and blogs
Trying to understand what's the correct way of implementing OpenID authentication with Spring Security.
Trying to understand the Deezer API. When I visit: http://connect.deezer.com/oauth/auth.php?app_id=MY_APP_ID&redirect_uri=http://mydomain.me&perms=basic_access I end up at
Trying to understand PNG format. Consider this PNG Image: The Image is taken from

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.