14

由于遗留原因,我需要使用侵入式指针,因为我需要能够将原始指针转换为智能指针。

但是我注意到没有用于提升的弱侵入指针。我确实在 boost 线程列表中找到了有关它的讨论,但没有具体内容。

有谁知道弱侵入指针的线程安全实现?

谢谢丰富

4

4 回答 4

11

这没有任何意义。

详细说明:weak_ptr指向同一个counter对象的实例shared_ptr。当shared_ptr超出范围时,实例会counter保留(有效计数为 0),这允许weak_ptr实例检查它们是否有效地指向已释放的对象。

使用侵入式计数,计数器集成在对象中。当计数达到 0 时,该对象通常要么被回收要么被删除......但关键是计数器不再可用。理由是这样可以实现更高效的存储(1 个单块)和更快的速度(缓存局部性)。

如果您需要弱引用计数并且不关心侵入式计数的好处,您可以使用shared_ptr和的组合weak_ptr

这个想法是解除计数器与对象的关联。

class Counted
{
  // bla
private:
  boost::shared_ptr<int> mCounter;
};

现在您可以返回弱句柄:

class WeakHandle
{
public:
  explicit WeakHandle(Counted& c): mCounter(c.mCounter), mObject(&c) {}

  bool expired() const { return mCounter.expired(); }

private:
  boost::weak_ptr<int> mCounter;
  Counted* mObject;
};

在这里,我们将计数器的生命周期与对象的生命周期解除关联,以便它能够在对象的破坏中幸存下来……部分。从而使weak_ptr有效成为可能。

当然,使用shared_ptrweak_ptr是线程安全的;)

于 2010-03-08T12:12:11.803 回答
6

我不太喜欢以前的任何一个答案,所以:

不,我不知道实现,但我认为这是可能的。shared_ptr 的标准实现包含两个引用计数,一个用于“强”引用,一个用于“弱”引用,以及一个指向所指对象的指针。在 intrusive_ptr 实现中,强计数必须是对象的一部分,但弱计数不能。因此,您似乎可以创建一个“弱”的 intrusive_ptr。

定义一个弱指针助手:

template<class X>
class intrusive_ptr_weak_helper {
    long weak_ref_count;
    X *target_instance;
};

然后将其记录到引用计数旁边的对象中:

struct X {
    ...
    intrusive_ptr_weak_helper *ref_weak_helper;
    ...
    long ref_count;
    ...
};

构建 X 时:

ref_count = 0;
ref_weak_helper = NULL;

“强”指针 intrusive_strong_ptr 与 intrusive_ptr 相同,直到发生删除。当强引用计数变为零时(在删除发生之前):

if (ref_weak_helper != NULL) {
    if (ref_weak_helper->weak_ref_count == 0)
        delete ref_weak_helper;
    else
        ref_weak_helper->target_instance = NULL;
}

“弱”版本,intrusive_weak_ptr,记录指向弱助手的指针,操纵引用计数,并通过 target_instance 指针访问目标对象。当weak_ref_count 减为零时,target_instance 的状态决定了助手是否被删除。

缺少许多细节(例如并发问题),但这是 shared_ptr 和 intrusive_ptr 的混合。它保持了 intrusive_ptr 的基本优点(缓存优化、重用 3rd 方侵入式(强)引用计数、强和弱指针替代是指针大小的),同时主要在弱引用路径中增加了额外的工作。

于 2015-02-27T01:23:50.360 回答
4

侵入式指针的当前实现是使用引用计数器。所以删除对象delete也会删除计数器,所以weak_intrusive_pointer永远不会知道对象被删除了。

如果您需要从中获取 weak_ptr this,您可能会搜索boost::enable_shared_from_this<T>.

于 2010-03-08T10:50:46.400 回答
1

OpenSceneGraph 及其后继者 VulkanSceneGraph 都具有侵入式强指针和相关弱指针的全面实现,分别命名为 ref_ptr<> 和 observer_ptr<>。

我不知道这些系统的每一个细节,但似乎它们使用一个额外的对象工作,该对象在删除所指对象(引用类的后代)时得到通知。当尝试将弱指针转换为强指针时,弱指针使用这第三个对象。

VulkanSceneGraph 是目前正在开发的下一代场景图,旨在取代 OpenSceneGraph,因此我认为它的侵入式指针系统是一种更高级的实现。

值得一试:

https://github.com/vsg-dev/VulkanSceneGraph/blob/master/include/vsg/core/observer_ptr.h

于 2020-07-10T14:33:27.297 回答