使用 enabled_shared_from_this
时似乎有一些边缘情况。例如:
boost shared_from_this and multiple inheritance
shared_from_this
是否可以在不使用 enable_shared_from_this
的情况下实现?如果是这样,它能做得同样快吗?
最佳答案
A shared_ptr
是3件事。它是一个引用计数器、一个破坏者和一个拥有的资源。
当你make_shared
,它一次分配所有 3 个,然后在那个 block 中构造它们。
当您创建 shared_ptr<T>
来自T*
,您单独创建引用计数器/销毁器,并注意拥有的资源是 T*
.
shared_from_this
的目标是我们可以提取一个shared_ptr<T>
来自T*
基本上(假设它存在)。
如果所有共享指针都是通过 make_shared
创建的,这很容易(除非您想要定义失败时的行为),因为布局很简单。
然而,并非所有共享指针都是以这种方式创建的。有时您可以创建一个共享指针,指向一个不是由任何 std
创建的对象。库函数,因此 T*
与共享指针引用计数和销毁数据无关。
因为在 T*
中没有房间或者它指向什么(通常)找到这样的构造,我们必须将它存储在外部,这意味着全局状态和线程安全开销和其他痛苦。这对不需要的人来说是一种负担 shared_from_this
,并且与确实需要它的人(互斥锁、查找等)的当前状态相比,性能受到了影响。
当前的设计存储一个 weak_ptr<T>
在enable_shared_from_this<T>
.这weak_ptr
每当 make_shared
时被初始化或 shared_ptr<T>
构造函数被调用。现在我们可以创建一个 shared_ptr<T>
来自 T*
因为我们通过继承 enable_shared_from_this<T>
在类里面为它“腾出了空间” .
这也是极低的成本,并且可以很好地处理简单的情况。我们最终得到一个开销 weak_ptr<T>
超过 T
的基准成本.
当你有两个不同的 shared_from_this
, 他们的 weak_ptr<A>
和 weak_ptr<B>
成员是不相关的,所以你想在哪里存储生成的智能指针(可能两者都有?)是不明确的。这种歧义会导致您看到错误,因为它假定只有一个 weak_ptr<?>
。一个独特的成员shared_from_this<?>
实际上有两个。
The linked solution提供了一种聪明的方法来扩展它。它写道 enable_shared_from_this_virtual<T>
.
这里不是存储 weak_ptr<T>
,我们存储一个 weak_ptr<Q>
其中 Q
是 enable_shared_from_this_virtual<T>
的虚基类,并且在虚拟基类中唯一地这样做。然后它会非虚拟地覆盖 shared_from_this
和类似的方法来提供与 shared_from_this<T>
相同的界面确实使用“成员指针或子类型 shared_ptr
构造函数”,您可以在其中以类型安全的方式将引用计数/破坏者组件与拥有的资源组件分开。
这里的开销大于基本shared_from_this
: 它具有虚拟继承并强制使用虚拟析构函数,这意味着该对象存储指向虚拟函数表的指针,并可以访问shared_from_this
。速度较慢,因为它需要虚函数表分派(dispatch)。
优点是它“可以正常工作”。现在有一个独特的 shared_from_this<?>
在层次结构中,您仍然可以获得指向类的类型安全共享指针 T
继承自 shared_from_this<T>
.
关于c++ - 没有enable_shared_from_this 可以实现shared_from_this 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28052672/