【C++】 37_智能指針分析

永恆的話題

  • 內存泄漏(臭名昭著的 Bug)ios

    • 動態申請堆空間,用完後不歸還
    • C++ 語言中沒有垃圾回收的機制
    • 指針沒法控制所指堆空間的生命週期

編程實驗: 內存泄漏

#include <iostream>
#include <string>

using namespace std;

class Test
{
private:
    int i;
public:
    Test(int i)
    {
        this->i = i;
    }
    int value()
    {
        return i;
    }
    ~Test()
    {
    }
};

int main()
{
    for(int i=0; i<5; i++)          // 若是是 5000000 次呢?
    {
        Test* p = new Test(i);
        
        cout << p->value() << endl;
    }

    return 0;
}
輸出:
0
1
2
3
4

深度的思考

  • 咱們須要什麼編程

    • 須要一個特殊的指針
    • 指針生命週期結束時主動釋放堆空間
    • 一塊堆空間最多隻能由一個指針表示(避免內存屢次釋放)
    • 杜絕指針運算和指針比較(避免越界形成野指針)

智指針分析

  • 解決方案函數

    • 重載指針特徵操做符( -> 和 *)
    • 只能經過類的成員函數重載
    • 重載函數不能使用參數(只能定義一個重載函數)

編程實驗: 智能指針

#include <iostream>
#include <string>

using namespace std;

class Test
{
private:
    int i;
public:
    Test(int i)
    {
        cout << "Test(int i)" << endl;
        this->i = i;
    }
    int value()
    {
        return i;
    }
    ~Test()
    {
        cout << "~Test()" << endl;
    }
};

class Poniter
{
private:
    Test* m_pointer;
public:
    Poniter(Test* p = NULL)
    {
        m_pointer = p;
    }
    Poniter(const Poniter& obj)
    {
        m_pointer = obj.m_pointer;                    // 全部權轉接
        const_cast<Poniter&>(obj).m_pointer = NULL;
    }
    Poniter& operator = (const Poniter& obj)
    {    
        if( this != &obj )
        {
            delete m_pointer;                         // 全部權轉接
            m_pointer = obj.m_pointer;
            const_cast<Poniter&>(obj).m_pointer = NULL;        
        }
        
        return *this;
    }
    Test* operator -> ()
    {
        return m_pointer;
    }
    Test& operator * ()
    {
        return *m_pointer;
    }
    bool isNull()
    {
        return (m_pointer == NULL);
    }
    ~Poniter()
    {
        delete m_pointer; 
    }
};

int main()
{
    Poniter p1 = new Test(0);
    
    cout << p1->value() << endl;
    
    Poniter p2 = p1;
    
    cout << p1.isNull() << endl;
    cout << p2->value() << endl;

    return 0;
}
輸出:
Test(int i)
0
1
0
~Test()
  • 智能指針的使用軍規: 只能用來指向堆空間中的對象或者變量

小結

  • 指針特徵操做符 ( -> 和 * ) 能夠被重載
  • 重載指針特徵符可以使用對象代替指針
  • 智能指針只能用於指向堆空間中的內存
  • 智能指針的意義在於最大程序的避免內存問題

以上內容參考狄泰軟件學院系列課程,請你們保護原創this