智能指針:它的一種通用實現方法是采用引用計數的方法。智能指針將一個計數器與類指向的對象相關聯,引用計數跟蹤共有多少個類對象共享同一指針。
每次創建類的新對象時,初始化指針並將引用計數置為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; }
使用該方式的內存結構圖如下: