C++中智能指針的工作原理和簡單實現


    智能指針:它的一種通用實現方法是采用引用計數的方法。智能指針將一個計數器與類指向的對象相關聯,引用計數跟蹤共有多少個類對象共享同一指針。

    每次創建類的新對象時,初始化指針並將引用計數置為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;
}

  

 
使用該方式的內存結構圖如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM