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; };