Search code examples
c++boostshared-ptr

boost shared pointer constructor destructor


The following code

struct Base
{
  public:
  Base()
  {
    std::cout<<"Base Ctr";
  }

  ~Base()
  {
    std::cout<<"Base Dtr";
  }
};

struct Derived : Base
{
  Derived()
  {
    std::cout<<"Derived Ctr";
  }

  ~Base()
  {
    std::cout<<"Derived Dtr";
  }
};

int main()
{
  Base* b = new Derived;
  delete b;
}

gives me the following output :

Base Ctr
Derived Ctr
Base Dtr

The solution to this is to make the base destructor virtual.

However when I use boost smart pointers without virtual base destructor. I get a different output.

int main()
{
  boost::shared_ptr<Base> b = boost::make_shared<Derived>();
}

The output is

 Base Ctr
 Derived Ctr
 Derived Dtr
 Base Dtr

How is boost shared_ptr able to achieve this without affecting(I'm assuming) the Base and Derived classes.
How does it scale it for multiple level inheritance, i.e base points to dervderv where dervderv is inherited from derv.

EDIT:

Most answers tell me that the "magic" happens in make_shared. I however get the same behaviour for the following code

boost::shared_ptr<Base> ptr(new Derived);  

Solution

  • A solution implemented using normal function pointers:

    #include <iostream>
    #include <boost/shared_ptr.hpp>
    #include <boost/make_shared.hpp>
    #include <typeinfo>
    
    using namespace std;
    
    struct Base{
    
      Base(){
        cout<<"Base ctor."<<endl;
      }
    
      ~Base(){
        cout<<"Base dtor."<<endl;
      }
    
    };
    
    struct Derv: Base{
    
      Derv():Base(){
        cout<<"Derv ctor."<<endl;
      }
    
      ~Derv(){
        cout<<"Derv dtor."<<endl;
      }
    
    };
    
    typedef void (*DEL)(void*);
    
    template<typename U>
    void deleter(void* ptr)
    {
      delete static_cast<U*>(ptr);
    }
    
    template<typename T>
    struct SmartPtr{
    
      T* memPtr;
    
      DEL func;
    
      template<typename U>
        SmartPtr(U* p):
          memPtr(p)
      {
        func = deleter<U>;
      }
    
      ~SmartPtr(){
    
          func(memPtr);
      }
    };
    int main()
    {
      //case 1
      SmartPtr<Base> ptrSmart1(new Derv());
    
      //case 2
      SmartPtr<Base> ptrSmart2(new Base());
    
      //case 3
      SmartPtr<Derv> ptrSmart3(new Derv());
    
      return 0;
    }