句柄的實現

兩種方法實現句柄類,分離計數更加靈活

頭文件

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章