2

介绍

Peter Weinhart 描述了如何使用 CRTP 设计一个通用的 intrusive_ptr 基类,它可以按如下方式使用:

class foo : intrusive_base<foo>
{
     // foo-specific code.
};

这种方法强加了所有foo对象都带有引用计数器的约束。假设我们foo有时按值保留,并且只想在我们有指针时支付引用计数器的价格。例如,有时我们想创建foo实例并移动它们,有时我们想foo在堆上分配。

从概念上讲,这种情况的正确机制是std::shared_ptr. 但是,在某些情况下需要原始指针,这会调用侵入式指针,例如,当通过采用 void 指针的 C API 传递指针时。在这种情况下,在将指针传递给不透明 API 之前会“引用”指针,而在取回指针时会“取消引用”。

拥有控制权foo,最好的方法可能是使用基于策略的实现,并拥有一个引用计数和基本版本的foo. 在无法控制的情况下foo,另一种设计将反转继承关系:

template <typename Base>
class intrusive : public Base
{
    // ?

private:
    std::atomic_size_t ref_count_;   
};

typedef intrusive<foo> intrusive_foo;

// Assume boost::intrusive_ptr as intrusive pointer implementation
boost::intrusive_ptr<intrusive_foo> x = new intrusive_foo;
{
    auto y = x;   // Semantics: boost::intrusive_ptr_add_ref(x.get())

    // At scope exit: boost::intrusive_ptr_release(x.get())
}

在上面提到的文章中,Peter 说这样一个“[ intrusive] 的通用实现将利用 C++0x 可变参数模板和完美的转发。”

问题

这样一个泛型intrusive类的实现会是什么样子?我可以看到它可能会受益于 C++11 继承构造函数,但我不清楚实际上将如何实现intrusive使用上述工具的主体。

4

1 回答 1

1

Usingmake_shared为您提供与侵入式指针相同的效率。

在这种情况下,在将指针传递给不透明 API 之前会“引用”指针,而在取回指针时会“取消引用”。

正如其他人所说,您可以使用从原始指针enable_shared_from_this中获取shared_ptr返回(只要shared_ptr系统中至少有一个仍然拥有该对象的位置)

但要回答主要问题,我假设他的意思是使用可变参数模板和完美转发来定义构造函数,它看起来像:

template <typename Base>
  class intrusive : public Base
  {
    template<typename... Args>
      intrusive(Args&&... args)
      : Base(std::forward<Args>(args)...), ref_count_(0)
      { }

这允许您intrusive使用任意数量的任何类型的参数构造 ,并将它们转发到Base,因此您可以使用可用于构造的任何参数构造它 a Base

另一种选择是使用 C++11 继承构造函数(在任何编译器 AFAIK 中都没有实现)

template <typename Base>
  class intrusive : public Base
  {
    using Base::Base;
于 2012-05-06T13:49:04.023 回答