【问题标题】:how boost::~shared_ptr works?boost::~shared_ptr 是如何工作的?
【发布时间】:2010-12-30 06:01:56
【问题描述】:

在阅读《Beyond the C++ Standard Library: An Introduction to Boost》时,我得到了一个非常有趣的例子:

class A  
{  
public:  
    virtual void sing()=0;  
protected:  
    virtual ~A() {};  
};

class B : public A
{  
public:  
    virtual void sing(  )  
    {  
       std::cout << "Do re mi fa so la"<<std::endl;;  
    }  
};  

我做了一些测试:

int main()
{  

//1  
std::auto_ptr<A> a(new B); //will not compile ,error: ‘virtual A::~A()’ is protected

//2
A *pa = new B;
delete pa;  //will not compile ,error: ‘virtual A::~A()’ is protected
delete (dynamic_cast<B*>(pa)); //ok

//3 
boost::shared_ptr<A> a(new B);//ok

}

我很好奇的是 ~shared_ptr 是如何工作的? 它是如何推导出派生类B的?

提前感谢您的帮助!

谢谢大家, 我写了一个关于 ~shared_ptr 如何工作的简单示例

class sp_counted_base
{
public:
    virtual ~sp_counted_base(){}
};

template<typename T>
class sp_counted_base_impl : public sp_counted_base
{
public:
    sp_counted_base_impl(T *t):t_(t){}
    ~sp_counted_base_impl(){delete t_;}
private:
    T *t_;
};


class shared_count
{
public:
    static int count_;
    template<typename T>
    shared_count(T *t):
        t_(new sp_counted_base_impl<T>(t))
    {
        count_ ++;
    }
    void release()
    {
        --count_;
        if(0 == count_) delete t_;
    }
    ~shared_count()
    {
        release();
    }
private:
    sp_counted_base *t_;
};
int shared_count::count_(0);

template<typename T>
class myautoptr
{
public:
    template<typename Y>
    myautoptr(Y* y):sc_(y),t_(y){}
    ~myautoptr(){ sc_.release();}
private:
    shared_count sc_;
    T *t_;
};

int main()
{
    myautoptr<A> a(new B);
}

关键是:

  1. 模板构造函数
  2. ~shared_ptr中没有删除的资源,被shared_count删除了

【问题讨论】:

    标签: c++ boost shared-ptr


    【解决方案1】:

    令人惊讶的是,这里的关键不是boost::shared_ptr 析构函数,而是它的构造函数。

    如果您查看boost/shared_ptr.hpp,您会发现shared_ptr&lt;T&gt; 并没有“简单地”拥有一个期望T * 的构造函数,而是:

    template<class Y>
    explicit shared_ptr( Y * p );
    

    //3 中,当您从B * 构造boost::shared_ptr 时,不会发生到A * 的转换,并且shared_ptr 内部是使用实际的B 类型构建的。销毁对象后,删除发生在 B 指针上(而不是通过基类指针)。

    【讨论】:

    • 从技术上讲,它确实执行了从 B* 到 A* 的转换。对指针的所有后续访问都将使用 A* 类型。类型 B 的操作是通过标准多态性(它们通过 A*)。唯一的例外是析构函数,shared_ptr 通过其“删除器”机制(或其某种概括)记住它。
    【解决方案2】:

    shared_ptr 类模板有一个类类型为shared_count 的成员,而后者又具有一个指向类sp_counted_base 的类型指针的成员。类shared_count 的构造函数模板将指向类模板sp_counted_impl_p 的实例的指针分配给此成员,该成员由构造函数参数的类型而不是shared_ptr::value_type 模板化。 sp_counted_base 有一个纯虚成员函数dispose,它被sp_counted_impl_p 覆盖。因为sp_counted_impl_p 知道您的示例中的B 类型,所以它可以在不访问基类析构函数的情况下将其删除,并且因为它使用虚拟调度,所以类型是在运行时确定的。这种方法需要结合参数多态性和子类型多态性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-30
      • 1970-01-01
      • 2011-04-22
      相关资源
      最近更新 更多