c++ - 使用通用侵入式指针客户端进行引用计数

标签 c++ c++11 variadic-templates crtp

简介

Peter Weinhart 描述了如何设计 a generic intrusive_ptr base class using CRTP , 可以按如下方式使用:

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 说这样一个“[侵入式] 的通用实现将使用 C++0x 可变参数模板和完美转发。”

问题

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

最佳答案

使用 make_shared 可以获得与侵入式指针相同的效率。

In this case, one would "ref" the pointer before passing it to the opaque API and "unref" when getting it back.

正如其他人所说,您可以使用 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)
      { }

这允许您使用任意数量的任意类型的参数构造侵入式,并且它们将被转发到Base,因此您可以使用任何参数构造它可用于构造一个 Base

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

template <typename Base>
  class intrusive : public Base
  {
    using Base::Base;

关于c++ - 使用通用侵入式指针客户端进行引用计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9575647/

相关文章:

c++ - 我可以写 const expression double 是两个 ulp 小于 -0.5

c++ - 根据构成它的类型的存在有条件地定义一个成员变量

c++ - 如何在函数返回期间将 move 语义与 std::string 一起使用?

c++ - C++11中通过pthreads获取线程Core affinity

c++ - 可变参数模板函数的部分特化

c++ - 将可变参数模板参数与 lambda 结合起来

c++ - 最低 DirectX 9.0c 版本以及如何检查它

c++ - 在 C++ 中创建和初始化类

c++ - 在 C++ 中将字符串打印到临时流对象

c++ - C++ 11中的合取类型特征