enable_shared_from_this必须是第一个基类吗



我的类继承自多个基,其中一个是std::enable_shared_from_this。一定是一垒吗?

假设以下示例代码:

struct A { ~A(); };
struct B { ~B(); };
struct C : A, B, std::enable_shared_from_this<C> {};
std::make_shared<C>(); 

~A()~B()运行时,我能确定C所在的存储器仍然存在吗?

当~A((和~B((运行时,我能确定C所在的存储仍然存在吗?

否,基类的顺序无关紧要。即使是enable_shared_from_this的使用(或不使用(也是不重要的。

当一个C对象被破坏时(不管发生什么(,~C()将在~A()~B()之前被调用,因为这是基本析构函数的工作方式。如果您试图在基析构函数和其中的访问字段中"重建"C对象,那么这些字段将已经被销毁,因此您将获得未定义的行为。

~A()~B()运行时,我可以确定C所在的存储是否仍然存在?

当然!很难使用一个试图释放自己内存(它所在的内存(的基类。我甚至不确定它是否正式合法。

实现并没有做到这一点:当shared_ptr<T>被破坏或重置时,T的共享所有权的引用计数(RC(会减少(原子(;如果它在递减中达到0,则开始销毁/删除T

然后,当T不再存在时,weak-owners-or-T-exists计数(原子地(递减:我们需要知道我们是否是对控制块感兴趣的最后一个实体;如果减量给出非零结果,则意味着一些weak_ptr存在控制块的共享(可以是1共享,或100%(所有权,并且它们现在负责解除分配。

无论哪种方式,对于最后一个共同所有者,原子递减率在某个时刻都将为零值。

这里没有线程,没有非确定性,显然最后一个weak_ptr<T>是在C的销毁过程中销毁的。(你的问题中不成文的假设是没有保留其他weak_ptr<T>。(

破坏总是按照的精确顺序发生控制块用于销毁,因为shared_ptr<T>(通常(不知道(可能不同的(派生类的哪个(可能非虚拟的(销毁函数要调用。(控制块也知道make_shared的共享计数达到零时释放内存。(

实现之间唯一实际的变化似乎是关于内存围栏的精细细节,以及在常见情况下避免一些原子操作。

如果通过从基enable_shared_from_this<T>继承创建一个c类型的对象c,该对象具有基A、B和一个引用计数器,那么首先会为整个生成的对象分配内存,包括一般的基和基enable_shared_from_this<T>。直到最后一个所有者(也称为shared_ptr(放弃所有权,对象才会被销毁。那一刻~enable_shared~B和~A将在~C之后运行。在最后一个析构函数~A运行之前,完全分配的内存仍然保证在那里。运行~A之后,整个对象内存将被一下子释放。因此,为了回答您的问题:

当~A((和~B((运行时,我能确定C所在的存储仍然存在吗?

是的,尽管你不能合法访问它,但你为什么需要知道?你想避免哪个问题?

相关内容

  • 没有找到相关文章

最新更新