More Effective 的 Reference Counting
发觉计算机很多东西都是相同的,记得操作系统时候学过这一概率 copy on write,在Reference Counted中彻底用到,代码的设计确实精妙,可以在不修改客户端得类,利用RCIPtr间接指针,对客户端的类实现引用计数,太妙了,详细见代码吧,代码中Widget为已有的客户端的类,RCIPtr是一个间接指针,RCObject是引用计数的基类,所有需要引用计数的类都必须继承他,换句话说,RCObject类将引用计数逻辑封装了,而RCIPtr则是连接客户端类的纽带.
代码如下:
RCIPtr.h
#ifndef RCIPTR_H
#define RCIPTR_H
#include " RCObject.h "
template < class T >
class RCIPtr {
public :
RCIPtr(T* realPtr = 0);
RCIPtr(const RCIPtr& rhs);
~RCIPtr();
RCIPtr& operator=(const RCIPtr& rhs);
const T* operator->() const; //const version ->
T* operator->();
const T& operator*() const; //const version *
T& operator*();
int getRefCount() const; //测试用,获取指针所指向的对象的引用数
private :
struct CountHolder : public RCObject { //T的实际的指针保寸的地方
~CountHolder() {delete pointee;};
T* pointee;
};
CountHolder *counter;
void init(); //初始化公共代码
void makeCopy(); //Copy On Write的调用函数
} ;
#include " RCIPtr.cpp "
#endif
#define RCIPTR_H
#include " RCObject.h "
template < class T >
class RCIPtr {
public :
RCIPtr(T* realPtr = 0);
RCIPtr(const RCIPtr& rhs);
~RCIPtr();
RCIPtr& operator=(const RCIPtr& rhs);
const T* operator->() const; //const version ->
T* operator->();
const T& operator*() const; //const version *
T& operator*();
int getRefCount() const; //测试用,获取指针所指向的对象的引用数
private :
struct CountHolder : public RCObject { //T的实际的指针保寸的地方
~CountHolder() {delete pointee;};
T* pointee;
};
CountHolder *counter;
void init(); //初始化公共代码
void makeCopy(); //Copy On Write的调用函数
} ;
#include " RCIPtr.cpp "
#endif
RCIPtr.cpp
#ifdef RCIPTR_H
template < class T >
void RCIPtr < T > ::init() {
if (counter->isShareable() == false) {
T* oldValue = counter->pointee;
counter = new CountHolder;
counter->pointee = new T(*oldValue);
}
counter->addReference();
}
template < class T >
void RCIPtr < T > ::makeCopy() {
if (counter->isShared()) {
counter->removeReference();
T* oldValue = counter->pointee;
counter = new CountHolder;
counter->pointee = new T(*oldValue);
counter->addReference();
}
}
template < class T >
RCIPtr < T > ::RCIPtr(T * realPtr) : counter( new CountHolder) {
counter->pointee = realPtr;
init();
}
template < class T >
RCIPtr < T > ::RCIPtr( const RCIPtr & rhs) : counter(rhs.counter) {
init();
}
template < class T >
RCIPtr < T > :: ~ RCIPtr() {
counter->removeReference();
}
template < class T >
RCIPtr < T >& RCIPtr < T > :: operator = ( const RCIPtr & rhs) {
if (counter != rhs.counter) {
counter->removeReference();
counter = rhs.counter;
init();
}
return *this;
}
template < class T >
const T * RCIPtr < T > :: operator -> () const {
return counter->pointee;
}
template < class T >
T * RCIPtr < T > :: operator -> () {
makeCopy();
return counter->pointee;
}
template < class T >
const T & RCIPtr < T > :: operator * () const {
return *(counter->pointee);
}
template < class T >
T & RCIPtr < T > :: operator * () {
makeCopy();
return *(counter->pointee);
}
template < class T >
int RCIPtr < T > ::getRefCount() const {
return counter->getRefCount();
}
#endif
template < class T >
void RCIPtr < T > ::init() {
if (counter->isShareable() == false) {
T* oldValue = counter->pointee;
counter = new CountHolder;
counter->pointee = new T(*oldValue);
}
counter->addReference();
}
template < class T >
void RCIPtr < T > ::makeCopy() {
if (counter->isShared()) {
counter->removeReference();
T* oldValue = counter->pointee;
counter = new CountHolder;
counter->pointee = new T(*oldValue);
counter->addReference();
}
}
template < class T >
RCIPtr < T > ::RCIPtr(T * realPtr) : counter( new CountHolder) {
counter->pointee = realPtr;
init();
}
template < class T >
RCIPtr < T > ::RCIPtr( const RCIPtr & rhs) : counter(rhs.counter) {
init();
}
template < class T >
RCIPtr < T > :: ~ RCIPtr() {
counter->removeReference();
}
template < class T >
RCIPtr < T >& RCIPtr < T > :: operator = ( const RCIPtr & rhs) {
if (counter != rhs.counter) {
counter->removeReference();
counter = rhs.counter;
init();
}
return *this;
}
template < class T >
const T * RCIPtr < T > :: operator -> () const {
return counter->pointee;
}
template < class T >
T * RCIPtr < T > :: operator -> () {
makeCopy();
return counter->pointee;
}
template < class T >
const T & RCIPtr < T > :: operator * () const {
return *(counter->pointee);
}
template < class T >
T & RCIPtr < T > :: operator * () {
makeCopy();
return *(counter->pointee);
}
template < class T >
int RCIPtr < T > ::getRefCount() const {
return counter->getRefCount();
}
#endif
RCObject.h
#ifndef RCOBJECT_H
#define RCOBJECT_H
/**/ /**
* base class, 用于reference-counted objects
*/
class RCObject {
public :
void addReference(); //添加reference
void removeReference(); //删除reference
void markUnshareable(); //标记object不可共享
bool isShareable() const; //判断object是否可被共享
bool isShared() const; //判断object是否被共享中
int getRefCount() const; //获取对象的引用数
protected :
RCObject(); //RCObject default-constructor
RCObject(const RCObject& rhs); //RCObject copy-constructor
RCObject& operator=(const RCObject& rhs); //RCObject assignment
virtual ~RCObject() = 0;
private :
int refCount; //引用计数
bool shareable; //可否共享标记
} ;
#endif
#define RCOBJECT_H
/**/ /**
* base class, 用于reference-counted objects
*/
class RCObject {
public :
void addReference(); //添加reference
void removeReference(); //删除reference
void markUnshareable(); //标记object不可共享
bool isShareable() const; //判断object是否可被共享
bool isShared() const; //判断object是否被共享中
int getRefCount() const; //获取对象的引用数
protected :
RCObject(); //RCObject default-constructor
RCObject(const RCObject& rhs); //RCObject copy-constructor
RCObject& operator=(const RCObject& rhs); //RCObject assignment
virtual ~RCObject() = 0;
private :
int refCount; //引用计数
bool shareable; //可否共享标记
} ;
#endif
RCObject.cpp
#include
"
RCObject.h
"
RCObject::RCObject() : refCount( 0 ), shareable( true ) {
}
RCObject::RCObject( const RCObject & rhs) : refCount( 0 ), shareable( true ) {
}
RCObject & RCObject:: operator = ( const RCObject & rhs) {
return *this;
}
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;
}
int RCObject::getRefCount() const {
return refCount;
}
RCObject:: ~ RCObject() {
// delete this;
}
RCObject::RCObject() : refCount( 0 ), shareable( true ) {
}
RCObject::RCObject( const RCObject & rhs) : refCount( 0 ), shareable( true ) {
}
RCObject & RCObject:: operator = ( const RCObject & rhs) {
return *this;
}
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;
}
int RCObject::getRefCount() const {
return refCount;
}
RCObject:: ~ RCObject() {
// delete this;
}
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
/**/ /**
* Widget测试类
*/
class Widget {
public :
Widget(int size);
Widget(const Widget& rhs);
~Widget();
Widget& operator=(const Widget& rhs);
void setSize(int size);
int getSize() const;
void showSize() const;
private :
int mSize;
} ;
#endif
#define WIDGET_H
/**/ /**
* Widget测试类
*/
class Widget {
public :
Widget(int size);
Widget(const Widget& rhs);
~Widget();
Widget& operator=(const Widget& rhs);
void setSize(int size);
int getSize() const;
void showSize() const;
private :
int mSize;
} ;
#endif
Widget.cpp
#include
"
Widget.h
"
#include < iostream >
using namespace std;
Widget::Widget( int size) : mSize(size) {
}
Widget::Widget( const Widget & rhs) : mSize(rhs.mSize) {
}
Widget:: ~ Widget() {
}
Widget & Widget:: operator = ( const Widget & rhs) {
if (this == &rhs) {
return *this;
}
mSize = rhs.getSize();
return *this;
}
void Widget::setSize( int size) {
mSize = size;
}
int Widget::getSize() const {
return mSize;
}
void Widget::showSize() const {
cout << "Size of this Widget is " << mSize << endl;
}
#include < iostream >
using namespace std;
Widget::Widget( int size) : mSize(size) {
}
Widget::Widget( const Widget & rhs) : mSize(rhs.mSize) {
}
Widget:: ~ Widget() {
}
Widget & Widget:: operator = ( const Widget & rhs) {
if (this == &rhs) {
return *this;
}
mSize = rhs.getSize();
return *this;
}
void Widget::setSize( int size) {
mSize = size;
}
int Widget::getSize() const {
return mSize;
}
void Widget::showSize() const {
cout << "Size of this Widget is " << mSize << endl;
}
RCWidget.h
#ifndef RCWIDGET_H
#define RCWIDGET_H
#include " RCIPtr.h "
#include " Widget.h "
class RCWidget {
public :
RCWidget(int size);
void setSize(int size);
int getSize() const;
void showSize() const;
int getRefCount() const;
private :
RCIPtr<Widget> value;
} ;
#endif
#define RCWIDGET_H
#include " RCIPtr.h "
#include " Widget.h "
class RCWidget {
public :
RCWidget(int size);
void setSize(int size);
int getSize() const;
void showSize() const;
int getRefCount() const;
private :
RCIPtr<Widget> value;
} ;
#endif
RCWidget.cpp
#include
"
RCWidget.h
"
RCWidget::RCWidget( int size) : value( new Widget(size)) {
}
void RCWidget::setSize( int size) {
value->setSize(size);
}
int RCWidget::getSize() const {
return value->getSize();
}
void RCWidget::showSize() const {
value->showSize();
}
int RCWidget::getRefCount() const {
return value.getRefCount();
}
RCWidget::RCWidget( int size) : value( new Widget(size)) {
}
void RCWidget::setSize( int size) {
value->setSize(size);
}
int RCWidget::getSize() const {
return value->getSize();
}
void RCWidget::showSize() const {
value->showSize();
}
int RCWidget::getRefCount() const {
return value.getRefCount();
}
test.cpp
#include
"
RCWidget.h
"
#include < iostream >
using namespace std;
int main() {
RCWidget w(100);
RCWidget v(w);
v.showSize();
w.showSize();
cout << "v RCWidget RefCount is " << v.getRefCount() << endl;
cout << "w RCWidget RefCount is " << w.getRefCount() << endl;
v.setSize(20);
v.showSize();
w.showSize();
cout << "v RCWidget RefCount is " << v.getRefCount() << endl;
cout << "w RCWidget RefCount is " << w.getRefCount() << endl;
return 0;
}
#include < iostream >
using namespace std;
int main() {
RCWidget w(100);
RCWidget v(w);
v.showSize();
w.showSize();
cout << "v RCWidget RefCount is " << v.getRefCount() << endl;
cout << "w RCWidget RefCount is " << w.getRefCount() << endl;
v.setSize(20);
v.showSize();
w.showSize();
cout << "v RCWidget RefCount is " << v.getRefCount() << endl;
cout << "w RCWidget RefCount is " << w.getRefCount() << endl;
return 0;
}
Result :
Size of this Widget is 100
Size of this Widget is 100
v RCWidget RefCount is 2
w RCWidget RefCount is 2
Size of this Widget is 20
Size of this Widget is 100
v RCWidget RefCount is 1
w RCWidget RefCount is 1
Press any key to continue
只要每次写一个类似的RC类,就不用修改客户端已有的类,而又可以实现Reference-Counting了