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