智能指針:它的一種通用實現方法是采用引用計數的方法。智能指針將一個計數器與類指向的對象相關聯,引用計數跟蹤共有多少個類對象共享同一指針。
每次創建類的新對象時,初始化指針並將引用計數置為1;
當對象作為另一對象的副本而創建時,拷貝構造函數拷貝指針並增加與之相應的引用計數;
對一個對象進行賦值時,賦值操作符減少左操作數所指對象的引用計數(如果引用計數為減至0,則刪除對象),並增加右操作數所指對象的引用計數;這是因此左側的指針指向了右側指針所指向的對象,因此右指針所指向的對象的引用計數+1;
調用析構函數時,構造函數減少引用計數(如果引用計數減至0,則刪除基礎對象)。
實現智能指針有兩種經典策略:一是引入輔助類,二是使用句柄類。這里主要講一下引入輔助類的方法,看下面的例子:
class Point //基礎對象類,要做一個對Point類的智能指針
{
public:
Point(int xVal = 0, int yVal = 0):x(xVal),y(yVal) { }
int getX() const { return x; }
int getY() const { return y; }
void setX(int xVal) { x = xVal; }
void setY(int yVal) { y = yVal; }
private:
int x,y;
};
class RefPtr //輔助類
{//該類成員訪問權限全部為private,因為不想讓用戶直接使用該類
friend class SmartPtr; //定義智能指針類為友元,因為智能指針類需要直接操縱輔助類
RefPtr(Point *ptr):p(ptr), count(1) { }
~RefPtr() { delete p; }
int count; //引用計數
Point *p; //基礎對象指針
};
class SmartPtr //智能指針類
{
public:
SmartPtr(Point *ptr):rp(new RefPtr(ptr)) { } //構造函數
SmartPtr(const SmartPtr &sp):rp(sp.rp) { ++rp->count; } //復制構造函數
SmartPtr& operator=(const SmartPtr& rhs) { //重載賦值操作符
++rhs.rp->count; //首先將右操作數引用計數加1,
if(--rp->count == 0) //然后將引用計數減1,可以應對自賦值
delete rp;
rp = rhs.rp;
return *this;
}
~SmartPtr() { //析構函數
if(--rp->count == 0) //當引用計數減為0時,刪除輔助類對象指針,從而刪除基礎對象
delete rp;
}
private:
RefPtr *rp; //輔助類對象指針
};
int main()
{
Point *p1 = new Point(10, 8);
SmartPtr sp1(p1); //此時sp1.rp->count = 1
SmartPtr sp2(sp1); //首先將sp1.rp->count賦給sp2.rp->count,之后sp2.rp->count++,這時sp1,sp2的rp是同一個對象
Point *p2 = new Point(5, 5);
SmartPtr sp3(p2);
sp3 = sp1;
return 0;
}
使用該方式的內存結構圖如下:

