兩種方法實現句柄類,分離計數更加靈活
頭文件
#pragma once
//通過計數來達到,對同一個對象使用時,避免了拷貝的開銷,當需要修改時,才進行正真的拷貝,
//在使用的對象很大時很能提高性能
//什麼時候用指針語義 例如 內部變量是數組類型
//什麼時候用值語義 例如 內部變量是大對象、變長字符串
class Point
{
public:
Point();
Point(int x,int y);
int x() const;
int y() const;
Point& x(int nX);
Point& y(int nY);
private:
int xVal, yVal;
};
//用於計數類
class UPoint
{
private:
friend class MyHandle;
Point p;
int u;
UPoint():u(1){}
UPoint(int x,int y):p(x,y),u(1){}
UPoint(const Point& p0):p(p0),u(1){}
};
class MyHandle
{
public:
MyHandle();
MyHandle(int,int);
MyHandle(const Point&);
MyHandle(const MyHandle&);
MyHandle& operator=(const MyHandle&);
~MyHandle();
int x() const;
MyHandle& x(int);
int y() const;
MyHandle& y(int);
private:
void CopyOnWrite();
private:
UPoint *pU;
};
//-----------------分離引用計數-------------------------
//輔助計數類
class UseCount
{
public:
UseCount();
UseCount(const UseCount&);
UseCount& operator=(const UseCount&);
~UseCount();
bool only();
bool reattach(const UseCount&);
bool makeonly();
private:
int * p; //通過指向相同的地址達到共享計數 所以不能用 int p
};
class CHandle
{
public:
CHandle();
CHandle(int, int);
CHandle(const Point&);
CHandle(const CHandle&);
CHandle& operator=(const CHandle&);
~CHandle();
int x() const;
CHandle& x(int);
int y() const;
CHandle& y(int);
private:
Point* p;
UseCount u;
};
實現
#include "MyHandle.h"
Point::Point():xVal(0),yVal(0)
{
}
Point::Point(int x, int y):xVal(x),yVal(y)
{
}
int Point::x() const
{
return xVal;
}
int Point::y() const
{
return yVal;
}
Point & Point::x(int nX)
{
xVal = nX;
return *this;
}
Point & Point::y(int nY)
{
yVal = nY;
return *this;
}
MyHandle::MyHandle():pU(new UPoint)
{
}
MyHandle::MyHandle(int x, int y):pU(new UPoint(x,y))
{
}
MyHandle::MyHandle(const Point &p):pU(new UPoint(p))
{
}
MyHandle::MyHandle(const MyHandle &handle):pU(handle.pU)
{
++pU->u;
}
MyHandle & MyHandle::operator=(const MyHandle &handle)
{
++handle.pU->u; //右側增加計數
if (--pU->u == 0) //左側因爲要被賦值,故原指向計數要減少
delete pU;
pU = handle.pU;
return *this;
}
MyHandle::~MyHandle()
{
if (--pU->u == 0)
delete pU;
}
int MyHandle::x() const
{
return pU->p.x();
}
MyHandle & MyHandle::x(int x)
{
////指針語義 一改均改
//pU->p.x(x);
//return *this;
//值語義 真正得寫時複製
//引用爲多個時,在修改時創建一個新的對象,以起到真正的對象分離互不影響
CopyOnWrite();
pU->p.x(x);
return *this;
}
int MyHandle::y() const
{
return pU->p.y();
}
MyHandle & MyHandle::y(int y)
{
////指針語義
//pU->p.y(y);
//return *this;
CopyOnWrite();
pU->p.y(y);
return *this;
}
void MyHandle::CopyOnWrite()
{
if (pU->u != 1)
{
--pU->u;
pU = new UPoint(pU->p);
}
}
//-------------------分離引用計數--------------------------
CHandle::CHandle():p(new Point())
{
}
CHandle::CHandle(int x, int y) : p(new Point(x,y))
{
}
CHandle::CHandle(const Point &point) :p(new Point(point))
{
}
CHandle::CHandle(const CHandle &h)
{
p = h.p;
u = h.u;
}
CHandle & CHandle::operator=(const CHandle &h)
{
if (u.reattach(h.u))
delete p;
p = h.p;
return *this;
}
CHandle::~CHandle()
{
if (u.only())
{
delete p;
}
}
int CHandle::x() const
{
return p->x();
}
CHandle & CHandle::x(int x0)
{
if (u.makeonly())
p = new Point(*p);
p->x(x0);
return *this;
}
int CHandle::y() const
{
return p->y();
}
CHandle & CHandle::y(int y0)
{
if (u.makeonly())
p = new Point(*p);
p->y(y0);
return *this;
}
UseCount::UseCount():p(new int(1))
{
}
UseCount::UseCount(const UseCount &uc):p(uc.p)
{
++*p;
}
UseCount & UseCount::operator=(const UseCount &uc)
{
reattach(uc);
return *this;
}
UseCount::~UseCount()
{
if (--*p == 0)
delete p;
}
bool UseCount::only()
{
return *p == 1;
}
bool UseCount::reattach(const UseCount &uc)
{
++*uc.p;
if (--*p == 0)
{
delete p;
p = uc.p;
return true;
}
p = uc.p;
return false;
}
bool UseCount::makeonly()
{
if(*p == 1)
return false;
--*p;
p = new int(1);
return true;
}