利用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));
     }
 };
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()进行优化