• Reference counting这项技术,容许多个等值对象共享同一实值。此技术的倒退有两种动机,第一是为了简化heap object周边的簿记工作。它能够打消“记录对象拥有权”的负荷,因为当对象使用了reference counting技术,它便领有它本人。一旦不再有任何人应用它,它便会主动销毁本人。reference counting的第二个倒退动机则只是为了实现一种常识。如果许多对象有雷同的值,将那个值存储屡次是件愚昧的事。最好是让所有等值对象共享一份实值就好。
  • 以下是一个蕴含了Copy-On-Write技术的Reference counting基类,有趣味倡议去看看原书中的文章,作者一步步疏导写出这个类,写的很具体,这里因为篇幅起因就不赘述。

    // RCObject.h// template class,用来产生smart pointers-to-T objects;T必须继承自RCObject template<class T>class RCPtr {public:  RCPtr(T* realPtr = 0);  RCPtr(const RCPtr& rhs);  ~RCPtr();  RCPtr& operator=(const RCPtr& rhs);  T* operator->() const;  T& operator*() const;private:  T *pointee;  void init();};// base class,用于reference-counted objectsclass RCObject {public:  void addReference();  void removeReference();  void markUnshareable();  bool isShareable() const;  bool isShared() const;protected:  RCObject();  RCObject(const RCObject& rhs);  RCObject& operator=(const RCObject& rhs);  virtual ~RCObject() = 0;  private:  int refCount;  bool shareable;};// RCObject.cppRCObject::RCObject() : refCount(0), shareable(true) {}RCObject::RCObject(const RCObject& rhs) : refCount(0), shareable(true) {}RCObject& RCObject::operator=(const RCObject& rhs) {  return *this;}RCObject::~RCObject () {}void RCObject::addReference() {  ++refCount;}void RCObject::removeReference() {  if (--refCount == 0) {      delete this;  }}void RCObject::markUnshareable() {  shareable = false;}bool RCObject::isShareable() const {  return shareable;}bool RCObject::isShared() const {  return refCount > 1;}template<class T>void RCPtr<T>::init () {  if (pointee == 0)      return;  if (pointee->isShareable() == false) {      pointee = new T(*pointee);  }  pointee->addReference();}template<class T>RCPtr<T>::RCPtr(T* realPtr) : pointee(realPtr) {  init();}template<class T>RCPtr<T>::RCPtr(const RCPtr& rhs) : pointee(rhs.pointee) {  init();}template<class T>RCPtr<T>::~RCPtr() {  if (pointee) {      pointee->removeReference();  }}template<class T>RCPtr<T>& RCPtr<T>::operator=(const RCPtr& rhs){  if (pointee != rhs.pointee) {      if (pointee) {          pointee->removeReference();      }      pointee = rhs.pointee;      init();  }  return *this;}template<class T>T* RCPtr<T>::operator->() const {  return pointee;}template<class T>T& RCPtr<T>::operator*() const {  return *pointee;}
  • 而后,定义一个简略的String类,在String中蕴含示意其实值的struct StringValue,其中StringValue继承自下面的RCObject,使其领有援用计数的能力。String代码如下所示。

    // String.h// 应用性class,这是应用程序开发人员接触的层面#include <string.h>#include "RCObject.h"class String {public:  String(const char *initValue = "");  const char& operator[] (int index) const;  char& operator[] (int index);private:  // 以下struct用以体现字符串实值  struct StringValue : public RCObject {      char *data;      StringValue(const char *initValue);      StringValue(const StringValue& rhs);      void init(const char *initValue);      ~StringValue();  };  RCPtr<StringValue> value;};// String.cppvoid String::StringValue::init(const char *initValue) {  data = new char[strlen(initValue) + 1];  strcpy(data, initValue);}String::StringValue::StringValue(const char *initValue) {  init(initValue);}String::StringValue::StringValue(const StringValue& rhs) {  init(rhs.data);}String::StringValue::~StringValue() {  delete [] data;}String::String(const char *initValue) : value(new StringValue(initValue)) {}const char& String::operator[](int index) const {  return value->data[index];}char& String::operator[](int index) {  if (value->isShared()) {      value = new StringValue(value->data);  }  value->markUnshareable();  return value->data[index];}
  • 再来写个main,简略验证下。

    #include <String.h>#include <iostream>int main(){  String s1 = "hello";  String s2 = s1;  std::cout << "s1[3] = " << s1[3] << std::endl;  std::cout << "s2[3] = " << s2[3] << std::endl;  s2[3] = 'x';  std::cout << "s1[3] = " << s1[3] << std::endl;  std::cout << "s2[3] = " << s2[3] << std::endl;}
// 输入s1[3] = ls2[3] = ls1[3] = ls2[3] = x
  • Reference counting是个优化技术,其应用前提是:对象经常共享实值。如果这个假如失败,reference counting反而会赔上更多内存,执行更多代码。从另一个角度看,如果你的对象的确有“独特实值”的偏向,reference counting应可同时节俭你的工夫和空间。
  • 简略说,以下是应用reference counting改善效率的最适当机会:

    • 绝对少数的对象共享绝对大量的实值(必要)。
    • 对象实值的产生或销毁老本很高,或是它们应用许多内存(非必要)。