【问题标题】:reference counting with shared objects and reference object共享对象和引用对象的引用计数
【发布时间】:2014-02-10 21:57:00
【问题描述】:

基于下面对引用计数的描述:

“一个普通的“引用计数”习语涉及一个'共享对象'(带有 计数)和简单的 'reference objects' (不是 C++ 引用, 尽管语义相似)指的是共享 目的。 “参考对象”的构造函数和析构函数 负责调用共享上的 incref/decref 方法 目的。所以共享对象是自动统计的 活动的'参考对象。"(reference counted class and multithreading)

我在网上搜索并找到了这个例子:

namespace Optimized {
struct StringBuf {
    StringBuf();             // start off empty
   ~StringBuf();             // delete the buffer
    void Reserve( size_t n );// ensure len >= n

    char*    buf;            // allocated buffer
    size_t   len;            // length of buffer
    size_t   used;           // # chars actually used
    unsigned refs;           // reference count
};

class String {
  public:
    String();                // start off empty
   ~String();                // decrement reference count
                             //  (delete buffer if refs==0)
    String( const String& ); // point at same buffer and
                             //  increment reference count
    void   Append( char );   // append one character
  private:
    StringBuf* data_;
 };
}

  namespace Optimized {

   StringBuf::StringBuf() : buf(0), len(0), used(0), refs(1) { }

   StringBuf::~StringBuf() { delete[] buf; }

   void StringBuf::Reserve( size_t n ) {
    if( len < n ) {
    size_t newlen = max( len * 1.5, n );
    char*  newbuf = new char[ newlen ];
    copy( buf, buf+used, newbuf );

    delete[] buf;   // now all the real work is
    buf = newbuf;   //  done, so take ownership
    len = newlen;
    }
  }

  String::String() : data_(new StringBuf) { }
  String::~String() {
  if( --data_->refs < 1 ) {
    delete data_;
      }
    }
   String::String( const String& other )
    : data_(other.data_)
    {
      ++data_->refs;
    }
 }

这个例子是否满足上面描述的条件?我的意思是,它是否涉及共享对象(在这种情况下是 StringBuf 结构吗?)和引用对象(字符串类)?

【问题讨论】:

  • 有点?此处显示的代码在引用计数中起作用,但没有任何参与引用计数(即复制)的构造函数,很难确定它是否正确计数。 :-)
  • @Xarn 我添加了复制构造函数
  • 是的,看起来不错,虽然线程完全不安全。
  • @Xarn 使用 InterlockedDecrement, refs 的增量足以使其线程安全?
  • 我将不得不用“不知道”来回答那个问题。我不知道InterlockedIncrement 的语义,不想猜测。 (还要记住,线程安全有多种定义,需要同步的内容取决于为字符串提供的 API。对于任何重要的事情,您还需要某种形式的临界区。(考虑重新分配,访问通过 [] 运算符之类的位置字符))

标签: c++ reference-counting


【解决方案1】:

将业务逻辑与生命周期管理混合(几乎*)绝不是一个好主意。

因此,在 C++11 standard library 和众所周知的 Boost library 中使用引用计数的共享所有权在单独的模板类中实现,这些模板类封装了最常用的所有权方案。

在Boost library 这些是:

  • shared_ptr&lt;T&gt; - 与引用计数共享所有权(在创建特定原始指针T* 的shared_ptr&lt;T&gt; 的第一个实例时分配引用计数器)。

  • weak_ptr&lt;T&gt; - 如果 shared_ptr&lt;T&gt; 还活着,则可用于获取完整的句柄

  • *intrusive_ptr&lt;T&gt; - 与引用计数共享所有权,其中引用计数器是被管理对象的一部分。这个特定的课程是您想要达到的目标的一个例子,但已经达到了工业标准。

【讨论】:

  • 可以参考这个问题“是否涉及共享对象(在这种情况下是StringBuf结构吗?)和引用对象(String类)?”
  • 您的代码确实实现了引用计数,但与C++ 上下文中的想法完全不同。在shared_ptr&lt;T&gt; 中,共享对象将被隐藏并归template shared_ptr&lt;class&gt; 所有,引用对象将是T,并且引用对象永远不会知道任何关于引用计数器的信息。
  • 根据我的问题上面的描述,我们可以把Struct StringBuf当作共享对象,把String类当作引用对象吗?
猜你喜欢
  • 2015-10-18
  • 2019-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-01
相关资源
最近更新 更多