天天看點

引用計數需要注意的幾個地方

This is a trick worth knowing: nesting a struct in the private part of a class is a convenient way to give access to the struct to all the members of the class, but to deny access to everybody else (except, of course, friends of the class). 

引用計數的思考過程:

① 針對: std::cout << s[1]; s[2] = 'a'; 這兩種情況無法分辨operator [] 是用作寫還是讀,提出 copy-on-write

② 針對: s1 = s; s2 = s; char* px = &s[0]; 如果px重新指派,s1, s2将都被改寫,提出增加一個share标志,

                  對于任何非const的operator[]操作,都将标志設為false,且無法恢複

幾個需要說明的地方:

RCObject::RCObject(const RCObject&)
: refCount(0), shareable(true) {}
      

這個refCount為0,因為這是一個“構造函數”,一個新對象的refCount當然是0了。

RCObject& RCObject::operator=(const RCObject&)
{ return *this; }
      

這沒有關于refCount的操作,因為這是“值”本身的相關操作,不是使用和封裝這個值的類

1.複制構造函數

String& String::operator=(const String& rhs)

{

  if (value == rhs.value) {          // do nothing if the values

    return *this;                    // are already the same; this

  }                                  // subsumes the usual test of

                                     // this against &rhs (see Item E17)

  if (--value->refCount == 0) {      // destroy *this's value if

    delete value;                    // no one else is using it

  }

  value = rhs.value;                 // have *this share rhs's

  ++value->refCount;                 // value

  return *this;

}

2.. 指針、引用與寫時拷貝

大部分情況下,寫時拷貝可以同時保證效率和正确性。隻有一個揮之不去的問題。看一下這樣的代碼:

String s1 = "Hello";

char *p = &s1[1];

char& String::operator[](int index)

{

  if (value->refCount > 1) {

    --value->refCount;

    value = new StringValue(value->data);

  }

  value->shareable = false;           // add this

  return value->data[index];

}

引用計數的結構:

  • template<class T>                       // template class for smart
    class RCPtr {                           // pointers-to-T objects; T
    public:                                 // must inherit from RCObject
      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();
    };
    
    
    class RCObject {                       // base class for reference-
    public:                                // counted objects
      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;
    };
    
    class String {                           // class to be used by
    public:                                  // application developers
    
      String(const char *value = "");
    
      const char& operator[](int index) const;
      char& operator[](int index);
    
    private:
      // class representing string values
      struct StringValue: public RCObject {
        char *data;
    
        StringValue(const char *initValue);
        StringValue(const StringValue& rhs);
        void init(const char *initValue);
        ~StringValue();
      };
    
      RCPtr<StringValue> value;
    };
          

繼續閱讀