Boost共享指针构造函数析构函数

boost shared pointer constructor destructor

本文关键字:析构函数 构造函数 指针 共享 Boost      更新时间:2023-10-16

以下代码

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;
}

给出如下输出:

Base Ctr
Derived Ctr
Base Dtr

解决这个问题的方法是使基类析构函数为虚函数。

然而,当我使用boost智能指针没有虚基析构函数。我得到一个不同的输出

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

输出为

 Base Ctr
 Derived Ctr
 Derived Dtr
 Base Dtr

boost shared_ptr如何能够在不影响(我假设)基类和派生类的情况下实现这一点。
它如何扩展它的多级继承,即基点到dervderv其中dervderv继承自derv.

编辑:

大多数回答告诉我,"魔法"发生在make_shared中。然而,对于以下代码

,我得到了相同的行为
boost::shared_ptr<Base> ptr(new Derived);  

使用普通函数指针实现的解决方案:

#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;
}

简而言之,boost::smart_ptr包含指向对象的指针、引用计数和在析构函数中调用的deleter函数,当调用boost::make_shared<Derived>()时,它将创建Derived类的默认构造对象,deleter将指向Derived的析构函数。这应该适用于任何长度的继承链,但在基类中使用虚析构函数确实是强制性的。

考虑这种技术的下一个简化朴素示例实现:

#include <iostream>
#include <functional>
using namespace std;
struct Base
{
  public:
  Base()
  {
    std::cout<<"Base Ctr ";
  }
  ~Base()
  {
    std::cout<<"Base Dtr ";
  }
};
struct Derived : Base
{
  Derived()
  {
    std::cout<<"Derived Ctr ";
  }
  Derived(const Derived& d)
  {
    std::cout<<"Derived copy Ctr ";
  }
  ~Derived()
  {
    std::cout<<"Derived Dtr ";
  }
};
template <typename T>
void default_deleter(T* p) {
    delete p;
}
template <typename T>
struct pointer {
    pointer(T* p, std::function<void ()> d) : p_(p), deleter_(d) {}
    template <typename U>
    pointer(pointer<U> other) : p_(new U(*other.p_)), 
    deleter_(std::bind(&default_deleter<U>, (U*)p_)) {}
    template <typename Y>
    explicit pointer(Y* p) : p_(p), deleter_(std::bind(&default_deleter<Y>, p)) {}
    ~pointer() {
        deleter_();
    }
    T* p_;
    std::function<void ()> deleter_;
};

template <typename T>
pointer<T> make_pointer() {
    T* p = new T;
    return pointer<T>(p, std::bind(&default_deleter<T>, p));
}
int main() {
    pointer<Base> b = make_pointer<Derived>();
    pointer<Base> b2(new Derived);
    return 0;
}

输出为:

Base Ctr Derived Ctr Base Ctr Derived copy Ctr Derived Dtr Base Dtr Derived Dtr Base Dtr

派生类的析构函数被调用两次,因为有两个指针实例:一个是在make_pointer函数中创建的,另一个是在main函数中创建的。

Boost通过一个delete函子实现了这一点。默认实现对使用make_shared创建的类型调用delete