来自同一个enable_shared_from_this实例的两个shared_ptr

时间:2017-11-13 04:46:33

标签: c++ c++11 shared-ptr reference-counting weak-ptr

鉴于此类是 enable_shared_from_this

class connection : public std::enable_shared_from_this<connection>
{
   //...
};

假设我从相同的 std::shared_ptr创建了两个connection*实例,如下所示:

std::shared_ptr<connection> rc(new connection);

std::shared_ptr<connection> fc(rc.get(), [](connection const * c) {
                                   std::cout << "fake delete" << std::endl;
                               });

到目前为止它很好,因为资源{connection*}归 shared_ptr - rc所有,而且fc只是有一个假的删除者。

之后,我这样做:

auto sc = fc->shared_from_this();
//OR auto sc = rc->shared_from_this(); //does not make any difference!

现在哪个shared_ptr - rcfc - 会sc引用计数共享?换句话说,

std::cout << rc->use_count() << std::endl;
std::cout << fc->use_count() << std::endl;

这些印刷品应该是什么?我测试了此代码,而found rc似乎只有2引用fc只有1

我的问题是,为什么?什么应该是正确的行为及其理由

我正在使用C ++ 11和GCC 4.7.3

2 个答案:

答案 0 :(得分:1)

  

原始指针重载假定指向对象的所有权。因此,使用已由shared_ptr管理的对象(例如shared_ptr(ptr.get()))的原始指针重载构造shared_ptr可能会导致未定义的行为,即使该对象是从{{1 }}。    - http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr

在您的情况下,您将获得具有两个不同所有权信息块的共享指针,但总是递增该类的第一个共享指针实例的引用计数。

如果你删除了假冒删除者&#39;你得到双重免费问题。

答案 1 :(得分:0)

在C ++ 11上(更常见的是,在C ++ 17之前)

我们唯一知道的是:

  

[util.smartptr.enab] shared_from_this();:

     

要求: enable_shared_from_t这应该是T的可访问基类。*这应该是T类型的对象t的子对象。应该至少有一个拥有的shared_ptr实例p &安培;吨

     

返回:与p。

共享所有权的shared_ptr对象r      

后置条件: r.get()== this。

如果按字面意思读取,暗示如果fc-&gt; shared_from_this()返回rcfc 的副本,则未指定(虽然理智的实现只会分配给内部weak_ptr一次,因此行为应该与c ++ 17中的行为相同,正如您所观察到的那样。)

来自C ++ 17

情况很明显:enable_shared_from_this基本上是weak_ptr,由第一个shared_ptr构造函数(或make_shared工厂)分配,它看到它处于过期状态。

因此,rc设置weak_ptrfc不设置,fc->shared_from_this()返回rc的副本。只要所有fc.get()副本都被销毁,rc就会返回一个僵尸指针。 您观察到的行为是正确的

请注意,所有采用非空指针(最多是删除器和/或分配器)的shared_ptr构造函数将拥有指针并管理其生命周期,就好像它是重新构造的一样,唯一的区别是只有第一个将分配给enable_shared_from_this的weak_ptr,如果有的话。