7

鉴于此类是enable_shared_from_this

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

std::shared_ptr假设我创建了两个from 的实例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;

这些应该打印什么?我测试了这段代码,发现 rc似乎只有.2fc1

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

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

4

2 回答 2

1

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

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

如果您删除“假删除器”,您将获得双重免费问题。

于 2017-11-13T07:31:25.417 回答
0

在 C++11 上(更一般地说,在 C++17 之前)

我们唯一知道的是:

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

要求: enable_shared_from_this 应是 T 的可访问基类。 *this 应是 T 类型对象 t 的子对象。应至少有一个 shared_ptr 实例 p 拥有 &t。

返回:与 p 共享所有权的 shared_ptr 对象 r。

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

如果从字面上理解,则意味着如果 fc->shared_from_this() 返回rcorfc的副本,则它是未指定的(尽管理智的实现将简单地分配给内部的 weak_ptr 一次,因此行为应该与 c++17 的情况相同,正如你所观察到的)。


从 C++17 开始

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

因此,rc设置weak_ptrfcfc->shared_from_this()返回 的副本rcfc.get()一旦所有rc副本都被销毁,将返回一个僵尸指针。你观察到的行为是正确的

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

于 2017-11-13T08:40:28.993 回答