您的位置:首页 > 其它

struct、class和STL的统一内存管理

2012-12-22 09:44 429 查看
转自:http://blog.csdn.net/lifesider/article/details/6443375

利用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()进行优化
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: