boost shared_ptr的基础设计

时间:2012-07-26 12:26:26

标签: c++ boost

我试图理解boost shared_ptr类的底层设计。我想把它“移植”到fortran(不要问)。我理解的一件事是引用计数由shared_count类保存。这提示我一个问题。我很久没有使用过C ++了,也没用过boost。

假设我分配了一个类X的单个实例,然后将其传递给两个不同的shared_ptr实例。根据我的理解,每个shared_ptr实例都不知道关于另一个的任何内容,因此两个shared_ptr实例都引用相同的X实例,同时保持引用计数为1.如果一个shared_ptr超出范围而另一个没有,则X对象将被删除(因为refcount降为零),剩下的shared_ptr将有一个悬空指针。为了保持shared_ptr refcount,你必须从另一个shared_ptr创建一个shared_ptr。

我是对的吗?如果没有,那么如何提升跟踪哪些shared_ptrs引用了一个对通过shared_ptrs引用的事实一无所知的类?

2 个答案:

答案 0 :(得分:7)

基本上你是对的。您的示例将导致悬空指针(请注意,如果您使用boost::enable_shared_from_this作为基类,则会有一些例外情况。)

说明

问题

boost:shared_ptrstd::shared_ptr有着相同的想法:创建一个带有来自原始指针的引用计数的智能指针。但是,它们也会遇到所有智能指针都存在的相同问题:如果你使用另一个智能指针中的原始指针而不是与你的其他智能指针相关联,你将以悬空指针结束多次调用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

“解决方案”

从原始指针S创建第一个智能指针p到对象O后,您应该只使用带有S的复制构造函数,而不是{{1}只要p不是std::enable_shared_from_this的派生词。 boost有点相当于此,但混合原始指针和智能指针仍然是一个坏主意。更好 - 如果使用智能指针,请不要使用原始指针:

O

更好的是,不要自己分配内存,而是使用std::make_sharedboost:make_shared

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

可能的实施

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 相比,以下实施非常粗糙,因为它不支持std::shared_ptrstd::weak_ptr。但是,它应该概述如何处理共享指针:

std::enable_shared_from_this

另见:

答案 1 :(得分:0)

这是boost::shared_ptr<X>的当前实现,但可以想到其他人不会分享这个缺点。例如。 static std::unordered_map<X*, int> std::shared_ptr<X>::share_count可用于跟踪每个shared_ptr<X>的{​​{1}}指针数量。但是,这样做的缺点是比简单的共享计数更大的开销。