C++引用计数(reference counting)技术简介(2)
来源:互联网 发布:塞班软件下载5233 编辑:程序博客网 时间:2024/06/05 19:34
1.一个引用计数(Reference-Counting)基类
Reference-counting可用于字符串以外的场合,任何class如果其不同的对象可能拥有相同的值,都适用此技术。但是如果重写class以便适用reference counting可能需要大量的工作。
我们可以设计一个引用计数基类RCObject,供想拥有引用计数的类继承。RCObject将“引用计数器”本身以及用以增减引用数值的函数封装起来。此外,还包括销毁对象值的函数,设置不可共享标的函数,返回共享标志的函数,查询是否在被共享的函数,查询引用计数的数目。没有必要提供一个设定共享标志位true的成员函数,因为所有的对象值在默认情况下都是可共享的。这里设定一旦某个对象被贴上”不可共享”标签,其永远都将是不可共享。
RCObject定义如下:
//引用计数基类 class RCObject{ public: RCObject();//构造函数 RCObject(const RCObject& rhs);//拷贝构造函数 RCObject& operator=(const RCObject& rhs);//拷贝赋值运算符 virtual ~RCObject() = 0;//析构函数 void addReference();//增加引用计数 void removeReference();//减少引用计数,如果变为0,销毁对象 void markUnshareable();//将可共享标志设为false bool isShareable() const;//判断其值是否可共享 bool isShared() const;//判断其值是否正在被共享 int getRefCount();//返回引用计数 private: int refCount;//保存引用计数 bool shareable;//保存其值是否可共享的状态 }; //构造函数,这里refCount设为0,让对象创建者自行或将refCoun设为1 RCObject::RCObject(void) :refCount(0), shareable(true){} //拷贝构造函数,总是将refCount设为0,因为正在产生一个新对象,只被创建者引用 RCObject::RCObject(const RCObject&) : refCount(0), shareable(true){} //拷贝赋值运算符,这里只返回*this,因为左右两方RCObject对象的外围对象个数不受影响 RCObject& RCObject::operator=(const RCObject& rhs){ return *this; } //析构函数 RCObject::~RCObject(){} //增加引用计数 void RCObject::addReference(){ ++refCount; } //减少引用计数,如果变为0,销毁对象 void RCObject::removeReference(){ if (--refCount == 0) delete this; } //将追踪其值是否可共享的成员设为false void RCObject::markUnshareable(){ shareable = false; } //判断其值是否可共享 bool RCObject::isShareable() const{ return shareable; } //判断其值是否正在被共享 bool RCObject::isShared() const{ return refCount>1; } //返回引用计数 int RCObject::getRefCount(){ return refCount; }
注意:
(1)RCObject的赋值运算符opeator=()什么也没有做,实际上可共享的实值实际不太可能被赋值。例如在自定义String类中,实值StringValue并不不会被赋值,而是String对象的赋值。
(2)RCObject::removeReference的责任不只在于将对象的refCount递减,而有当引用计数refCount为0时,销毁实值对象。使用delete this来销毁实值对象,那就要求*this是heap对象。
2.基于引用计数基类的String
基于引用计数的基类String设计如下:
class String{private: Struct StringValue:public RCObject{ char* data; StringValue(const char* initValue); ~StringValue(); }; StringValue* value; public: String(const char* initValue="");//constructor String(const String& rhs);//copy constructor String& operator=(const String& rhs); //assignment operator ~String(); //destructor};//StringValue的构造函数String::StringValue::StringValue(const char* initValue):refCount(1){ data=new char[strlen(initValue)+1]; strcpy(data,initValue); }//StringValue的析构函数String::StringValue::~StringValue(){ delete[] data;}
这一版本的StringValue几乎与前一版本完全相同,唯一的改变是StringValue的member functions不再处理引用计数refCount字段,改由RCObject掌握。
3.自动操作引用次数(Reference Count)
RCObject class存放了引用次数,也给出了操作引用次数的member fucntions,这些函数的调用动作还是得用户手动写到其他的class内,并且通过String constructor和String assignment operator调用StringValue对象所提供的addReference和removeReference。这里,我们使用可复用的类,不必让用户类去操作引用次数。这里可复用的类产生的对象我们呢称之为smart pointer。
下面使用template来实现smart pointers,指向reference-counted实值对象。
//智能指针模板类,用来自动执行引用计数实值类成员的操控动作 template<typename 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; //dumb pointer void init(); //共同的初始化操作 }; //共同的初始化操作 template<typename T> void RCPtr<T>::init(){ if (pointee == 0) return; if (pointee->isShareable() == false) { pointee = new T(*pointee); } pointee->addReference(); } //构造函数 template<typename T> RCPtr<T>::RCPtr(T* realPtr) :pointee(realPtr){ init(); } //拷贝构造函数 template<typename T> RCPtr<T>::RCPtr(const RCPtr& rhs) : pointee(rhs.pointee){ init(); } //析构函数 template<typename T> RCPtr<T>::~RCPtr(){ if (pointee) pointee->removeReference(); } //赋值运算符 template<typename T> RCPtr<T>& RCPtr<T>::operator=(const RCPtr& rhs){ if (pointee != rhs.pointee) { if (pointee) pointee->removeReference(); pointee = rhs.pointee; init(); } return *this; } //重载成员选取运算符 -> template<typename T> T* RCPtr<T>::operator->() const { return pointee; } //重载解引用运算符* template<typename T> T& RCPtr<T>::operator*() const { return *pointee; }
4.最终String
在上面的基础之上,我们利用具有服用性质的RCObject和RCPtr classes为基础,建造一个reference-counted String class。每一个具有引用计数功能的String对象均以此数据结构实现出来:
最终的String描述如下:
class String { public: String(const char *value = "");//构造函数 const char& operator[](int index) const;//重载[]运算符,针对const Strings char& operator[](int index);//重载[]运算符,针对non-const Strings private: struct StringValue : public RCObject {//继承自引用计数基类 char *data; StringValue(const char *initValue);//构造函数 StringValue(const StringValue& rhs);//拷贝赋值运算符 void init(const char *initValue); ~StringValue();//析构函数 }; RCPtr<StringValue> value;//智能指针对象 }; //String::StringValue实现代码 void String::StringValue::init(const char *initValue){ data = new char[strlen(initValue) + 1]; strcpy(data, initValue); } //StringValue类的构造函数 String::StringValue::StringValue(const char *initValue){ init(initValue); } //StringValue类的拷贝赋值运算符 String::StringValue::StringValue(const StringValue& rhs){ init(rhs.data); } //StringValue类的析构函数 String::StringValue::~StringValue(){ delete[] data; } //String实现代码 //String类的构造函数 String::String(const char *initValue): value(new StringValue(initValue)) {} //重载[]运算符,针对const Strings const char& String::operator[](int index) const{ return value->data[index]; } //重载[]运算符,针对non-const Strings char& String::operator[](int index){ if (value->isShared()) { value = new StringValue(value->data); } value->markUnshareable(); return value->data[index]; }
注意,这里使用智能指针对象的String并不需要显示定义copy constructor和assignment operator,因为这些编译器为默认生成,并且会自动调用String内RCPtr member的copy constructor和assignment operator,而后者又会自动执行对StringValue对象的所有处理,包括引用次数。
[1]More Effective C++.Scott Meyers著,侯捷译.P183-213.
[2]http://blog.csdn.net/ruan875417/article/details/48267527.
- C++引用计数(reference counting)技术简介(2)
- C++引用计数(reference counting)技术简介(1)
- C++引用计数(reference counting)技术简介(3)
- 各种算法-引用计数(reference counting)
- 【more effective c++读书笔记】【第5章】技术(5)——Reference counting(引用计数)(2)
- 避免重复的对象构建 ——Reference Counting(引用计数)技术
- Swift-自动引用计数(Automatic Reference Counting)(十四)
- 自动引用计数(ARC Automatic Reference Counting)
- Swift 自动引用计数(Automatic Reference Counting)
- Swift 自动引用计数(Automatic Reference Counting, ARC)
- 【more effective c++读书笔记】【第5章】技术(5)——Reference counting(引用计数)(1)
- 引用计数(Reference Counting)和代理(Proxy)的应用
- Swift学习笔记16——自动引用计数(Automatic Reference Counting)
- 对照Java学习Swift--自动引用计数(Automatic Reference Counting)
- c++ reference counting引用计数原理
- Automatic Reference Counting (ARC) 自动引用计数
- Automatic Reference Counting (ARC) 自动引用计数
- c++ reference counting引用计数原理
- QRCode--根据系统API, 封装二维码扫描
- Google推荐的图片加载库Glide介绍以及与picasso区别
- Spring事务管理只对出现运行期异常进行回滚
- LoadRunner的text验证及关联
- 你所不知道的python特点及语句
- C++引用计数(reference counting)技术简介(2)
- Apache Maven 入门篇 ( 上 )
- uva1267 - Network
- 外贸人都必须知道的国际贸易壁垒
- 移植mplayer到itop4412开发板
- Android WebView使用实例(html5、文件下载和远程URL)
- 装饰模式(Decorator Pattern)
- 使apk具有system权限
- java web 过滤器跟拦截器的区别和使用