标签:style blog http color io os ar 使用 strong
之前文章中实现的写时复制,句柄类中引用计数和T类型指针是分开的,这里换一种方式来处理,将引用计数和T类型指针视为一个整体,当做句柄类模板参数。先对上节中的引用计数进行改造:
1 class CUseCount
2 {
3 public:
4 CUseCount();
5 CUseCount(const CUseCount&);
6 CUseCount& operator=(const CUseCount&);
7 ~CUseCount();
8
9 void markUnshareable();
10 bool isShareable() const;
11 bool isShared() const;
12
13 void addReference();
14 void removeReference();
15
16 private:
17 int refCount; //注意这里非int指针
18 bool shareable; //是否是共享状态
19 };
20
21 CUseCount::CUseCount():refCount(0), shareable(true)
22 {}
23
24 CUseCount::CUseCount(const CUseCount& u):refCount(0), shareable(true)
25 {}
26
27 CUseCount& CUseCount::operator=(const CUseCount& u)
28 {
29 return *this;
30 }
31
32 CUseCount::~CUseCount()
33 {}
34
35 void CUseCount::markUnshareable()
36 {
37 shareable = false;
38 }
39
40 bool CUseCount::isShareable() const
41 {
42 return shareable;
43 }
44
45 bool CUseCount::isShared() const
46 {
47 return refCount > 1;
48 }
49
50 void CUseCount::addReference()
51 {
52 ++refCount;
53 }
54
55 void CUseCount::removeReference()
56 {
57 if(--refCount == 0)
58 delete this;
59 }
这个版本的UseCount和之前的版本差别很大,从析构函数可以看出(纯虚函数),它是基于引用计数来共享的值对象的基类,需要注意的部分:
接下来看看这一版本中的Handle类:
1 template<class T> class Handle
2 {
3 public:
4 Handle(T *p = 0);
5 Handle(const Handle& h);
6 Handle& operator=(const Handle&);
7 ~Handle();
8 //other member functions
9 private:
10 T* ptr;
11 void init();
12 };
13
14 template<class T>
15 inline Handle<T>::init()
16 {
17 if(ptr == 0)
18 return;
19 if(ptr->isShareable() == false) //非共享状态,进行复制
20 ptr = new T(*ptr);
21
22 ptr->addReference(); //引用计数增加
23 }
24
25 template<class T>
26 inline Handle<T>::Handle(T* p):ptr(p) //u 默认构造函数
27 {
28 init();
29 }
30
31 template<class T>
32 inline Handle<T>::Handle(const Handle& rhs):ptr(rhs.ptr)
33 {
34 init();
35 }
36
37 template<class T>
38 inline Handle<T>& Handle<T>::operator=(const Handle& rhs)
39 {
40 if(ptr != rhs.ptr)
41 {
42 if(ptr != NULL)
43 {
44 ptr->removeReference();
45 }
46 ptr = rhs.ptr;
47 init();
48 }
49 return *this;
50 }
51
52 template<class T>
53 inline Handle<T>::~Handle()
54 {
55 if(ptr)
56 ptr->removeReference();
57 }
修改后的Handle类比之前的要复杂一些:
使用本节中实现的UseCount和Handle来处理写时复制,一个String类的例子如下:
1 ?class String
2 {
3 public:
4 String(const char *value = "");
5 const char& operator[](int index) const;
6 char& operator[](int index);
7 private:
8 struct StringValue: public CUseCount //继承自引用计数
9 {
10 char *data;
11 StringValue(const char *initValue);
12 StringValue(const StringValue& rhs);
13 void init(const char *initValue);
14 ~StringValue();
15 };
16 Handle<StringValue> value;
17 };
18
19 void String::StringValue::init(const char *initValue)
20 {
21 data = new char[strlen(initValue) + 1];
22 strcpy(data, initValue);
23 }
24
25 String::StringValue::StringValue(const char *initValue)
26 {
27 init(initValue);
28 }
29
30 String::StringValue::StringValue(const StringValue& rhs)
31 {
32 init(rhs.data);
33 }
34
35 String::StringValue::~StringValue()
36 {
37 delete [] data;
38 }
39
40 String::String(const char *initValue): value(new StringValue(initValue))
41 {}
42
43 const char& String::operator[](int index) const //const函数不进行复制
44 {
45 return value->data[index];
46 }
47
48 char& String::operator[](int index)
49 {
50 if (value->isShared())
51 {
52 value = new StringValue(value->data); //先调用基类UseCount拷贝构造函数
53 }
54 value->markUnshareable();
55 return value->data[index];
56 }
代码中可以看出,String内部实现由StringValue完成,Handle句柄托管StringValue类型指针,StringValue继承自UseCount类,其子对象部分负责char*的管理,,父对象即UseCount完成对象的计数、共享以及销毁工作,以图来表示例子中各个类的关系如下:
代码中还有一些需要的地方:
1 char& String::operator[](int index)
2 {
3 if (value->isShareable())
4 {
5 value = new StringValue(value->data); //先调用基类UseCount拷贝构造函数
6 }
7 value->markUnshareable();
8 return value->data[index];
9 }
10
11 int main()
12 {
13 String s("Grubby");
14 char c = s[3];
15
16 return 0;
17 }
main函数中line14,调用了operator[] 操作符,按上述代码实现,line3先判断if(value->isShareable()),而s对象刚刚定义没有使用,UseCount构造函数中设置isShare=true,所以if判断返回true,运行语句value = new StringValue(value->data),重新构造value是没有必要的。而判断如果是if(isShared()),此时refCount==1,所以没有共享if返回false,不会重新构造value。
这一节中的代码,借鉴了《more effective C++》中的引用计数章节,加上了一些自己的个人理解,文章中不免有误,还请大家指正。
未完待续……
标签:style blog http color io os ar 使用 strong
原文地址:http://www.cnblogs.com/Tour/p/4043887.html