【C++】動態內存管理(三)不同的資源管理對象的實現

這裏我就直接貼代碼然後進行說明了。

拷貝型資源管理對象

對於普適性的資源,比如string、vector、array等資源,我們通常採用拷貝的方式進行資源的賦值操作
下面是這種資源管理對象的基本構造:

    template<typename T>
    class Data
    {
    private:
        T* pointer;
    public:
        Data(const Data& d) :pointer(new T(*(d.pointer))) {};
        Data() :pointer(NULL) {};
        Data(T* p) :pointer(p)
        {

        };
        ~Data() 
        {
            delete pointer;
        }
        T& operator*() { return *(this->pointer); }
        Data& operator =(Data rhs)
        {
            delete pointer;
            pointer = new T(*(rhs.pointer)); 
            return *this;
        }
    };

然後我們測試一下:

    void test()
    {
        Data<int> p1(new int(3));
        Data<int>p2 = p1;
        *p2 = 5;
        cout << *p1 << " "<<*p2<<endl;//輸出 3 5
    }

可以看到,當這種資源管理對象發生賦值的時候,就會產生新的資源副本,然後兩個對象的資源就此隔離沒有任何關係了。一個對象資源的改變不會影響另一個資源對象管理的資源

控制權轉移的資源管理對象

這種控制權交換的情況有很多,比如mutex的鎖等等臨界資源,也就是隻能被一個線程使用的資源,這樣的資源不能進行拷貝,只能進行支配權的轉移
大致構造如下:

    template<typename T>
    class Data
    {
    private:
        T* pointer;
    public:
        Data(Data& d):pointer( d.pointer)
        {
            d.pointer = NULL;
        };
        Data() :pointer(NULL) {};
        Data(T* p=NULL) :pointer(p)
        {

        };
        ~Data() 
        {
            delete pointer;
        }
        T& operator*() { return *(this->pointer); }
        Data& operator =(Data rhs)
        {
            delete pointer;
            pointer = rhs.pointer; 
            rhs.pointer = NULL;
            return *this;
        }
    };

當管理這種資源的對象進行賦值操作或則拷貝構造的時候,就會取消源資源對象對資源的的控制權,然後由新的資源管理對象對資源進行獨自的管理

只有一個本體(但能被多個對象訪問)的資源

還有一種資源,這種資源產生之後可以被大家共享。每個共享者實際上使用的都是同一個資源副本,當其中一個使用者被析構了不一定會釋放內存,而是所有使用者都被銷燬了,纔會釋放這塊資源佔據的內存。我們就添加一個計數器變量來統計使用者數量

下面就是一個簡略的計數型資源管理對象的設計:

    template<typename T>
    class Data
    {
    private:
        size_t* count;
        T* pointer;
    public:
        Data(const Data& d) :pointer(d.pointer), count(d.count) 
        {
            ++(*count);
        }

        Data() :pointer(NULL),count(NULL) {};
        Data(T* p = NULL) :pointer(p), count(new size_t(1)) {};

        ~Data()
        {
            cout << "~Data" << endl;
            if (--(*count) == 0)
            {
                delete pointer;
                delete count;
                cout << "無人訪問,刪除共享資源" << endl;
            }
        }

        T& operator*() { return *(this->pointer); }
        size_t user() { return *count; };
        Data& operator =(Data rhs)
        {
            pointer = rhs.pointer; 
            count = rhs.count;
            *(this->count) += 1;
            return *this;
        }
    };

由於在賦值和拷貝的時候要對這個資源的所有計數器都進行更新,所以使用了size* count(一個指針對象)來進行實時同步。並且提供user()來查看當前有多少使用者。

一個測試代碼:

void test()
    {
        Data<int> p1(new int(3));
        Data<int>p2 = p1;
        *p2 = 5;
        cout << *p1 << " " << *p2 << endl;
        cout << "user: " << p1.user() << endl;
    }

結果如下:

5 5
user: 2
~Data
~Data
無人訪問,刪除共享資源

可以看到,是很符合我們預期的,所有資源都可以很好的被分到不同的類別中去,然後進行不同類型資源的管理。保證資源的不同使用方法都能得到安全釋放。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章