struct、class和STL的統一內存管理

利用C++的new和delete操作符重載特性,可以對自定義的struct和class進行統一內存管理,再加上STL allocator的開放特性,便可以將STL容器對象的內存管理併入struct和class的內存管理,進而將這三者的內存管理統一。

 

首先實現自定義的內存管理算法框架,開放接口爲allocate和deallocate,實現庫爲memmgr.dll

class memory_manager

{

public:

      virtual void* allocate(size_t size) = 0;

      virtual void deallocate(void* ptr, size_t size) = 0;

}

 

通過顯示加載或隱式鏈接得到memmgr.dll導出的自定義內存管理框架接口指針

memory_manager* ptrmemmgr;

 

針對struct和class,建立公共基類,並調用導出的內存管理相關接口

class basic_object

{

public:

    void* operator new(size_t size)

    {

        return (ptrmemmgr->allocate(size);

    }

    void operator delete(void* ptr, size_t size);

    {

        ptrmemmgr->deallocate(ptr, size);

    }

};

 

自此,對於任意的自定義struct和class,都可以公共繼承自basic_object,調用new和delete時便會調用basic_object::new和basic_object::delete接口,如下示例

class example : public basic_object

{

public:

    // 這裏省略成員函數和成員變量的聲明和實現,就像沒有繼承自basic_object時一樣

};

 

當對example進行new和delete操作時,編譯器將產生調用basic_object::new和basic_object::delete的代碼

 

至此,已將struct和class的內存管理統一了

 

對於STL,由於STL的所有容器都有一個allocator的模板參數,因此我們需要自定義allocator

template<typename T>

class newallocator : public std::allocator<T>

{

public:

    template<typename O>

    struct rebind

    {

        typedef newallocator<O> other;

    }

    template<typename O>

    newallocator(newallocator<O> const&) throw()

    {

    }

    template<typename O>

    newallocator<T>& operator=(newallocator<O> const&) throw()

    {

        return (*this);

    }

    T* allocate(size_type count)

    {

        return (basic_object::operator new(count * sizeof(T));

    }

    void deallocate(T* ptr, size_type count)

    {

        basic_object::operator delete(ptr, count * sizeof(T));

    }

};

 

然後,對於任何容器,只需使用上面自定義的newallocator即可,如

std::vector<int, newallocator<int>> vtexample;

std::map<int, int, std::less<int>, newallocator<std::pair<int const, int>>> mapexample;

 

至此,STL容器的內存管理也併入memory_manager裏了,三者的內存管理達成統一。

 

注意:

(1)由於這裏只重載了operator new和operator delete,因此只爲struct和class的單個對象有效,對於數組仍會使用全局的::operator new[]和::operator dlete[]。當然也可以重載operator new[]和operator delete[]操作符,這樣便將數組的內存管理也併入memory_manager裏了。

(2)使用自定義的內存管理框架後,對於struct,由於有了成員函數,便不能使用聲明時初始化數組的方式,如

struct stu stuexample = {0};     // 這種使用方式將導致編譯錯誤,但可以使用memset(&stuexample, 0, sizeof(stu))

(3)可以爲operator new(或者new[])加入更多的參數,如文件名和行數,進行debug下的內存泄漏檢測

(4)重載operator delete[]時,應該使用operator delete[](void* ptr),否則使用operator delete[](void* ptr, size_t size)時傳入的參數size只是一個對象的大小,而不是整個數組的大小

(5)如果自定義實現的內存管理框架中可以保證不產生異常,對於basic_object和newallocator可以使用throw()進行優化

 

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