C++ STL 容器自定义内存分配器
来源:互联网 发布:js 观察者模式 实例 编辑:程序博客网 时间:2024/05/29 16:56
一,基础篇
很多时候我们不要用默认的allocator的实现,我们需要自己的内存配置,所以我们可以做自己的分配器,这里说说必须要有的一些注意事项,因为有些是我犯错过的。
- 需要有自己的一些类型定义比如pointer
- 需要做自己的allocate和deallocate
- 一定要有rebind实现,如果不理解,请看一下标准库里面的list,set等的实现,很容易的。
附上代码:
template <typename T>class MyAlloc : public allocator<T>{public: typedef size_t size_type; typedef typename allocator<T>::pointer pointer; typedef typename allocator<T>::value_type value_type;typedef typename allocator<T>::const_pointer const_pointer;typedef typename allocator<T>::reference reference;typedef typename allocator<T>::const_reference const_reference; template <typename U> struct rebind { typedef MyAlloc<U> other; }; pointer allocate(size_type _Count, const void* _Hint = NULL) {
4. 做了rebind之后。一定要实现默认构造函数和非同类型一个模板的复制构造函数,最后的代码就如下了:
class MaObjectDisplay1{private: string DisplayString;public: MaObjectDisplay1(const char *str) :DisplayString(str) { DisplayString += '\n'; } void operator() (const int &inObj) { printf("inobj %d\n", inObj); } bool operator < (const MaObjectDisplay1 & in) const { return false; }};//this alloc class is just for the stl set<> allocatortemplate <typename T>class MyAllc : public allocator<T>{public: typedef size_t size_type; typedef typename allocator<T>::pointer pointer; typedef typename allocator<T>::value_type value_type;typedef typename allocator<T>::const_pointer const_pointer;typedef typename allocator<T>::reference reference;typedef typename allocator<T>::const_reference const_reference; pointer allocate(size_type _Count, const void* _Hint = NULL) { void *rtn = NULL; //EthCFMMgntRbTreeMem::GetMemInstance()->malloc(_Count, rtn); return (pointer)rtn; } void deallocate(pointer _Ptr, size_type _Count) { //EthCFMMgntRbTreeMem::GetMemInstance()->free(_Ptr); } template<class _Other> struct rebind {// convert this type to allocator<_Other> typedef MyAllc<_Other> other; }; MyAllc() throw() {} MyAllc(const MyAllc& __a) throw() : allocator<T>(__a) {} template<typename _Tp1> MyAllc(const MyAllc<_Tp1>&) throw() {} ~MyAllc() throw() {}};int main(){ set<MaObjectDisplay1, less<MaObjectDisplay1 >, MyAllc<MaObjectDisplay1> > myset; MaObjectDisplay1 a("asdf"); myset.insert(a);}
二、进阶篇 (一)
如果需要内存分配释放有不同的实现,那么,就需要把分配器扩展了,我们可以先试试使用模板参数来提供内存的分配和释放的核心,如下:
#include <stdio.h>#include <set>using namespace std;class M1{public: static void *getMem(int size) { return malloc(size); } static void putMem(void *ptr) { return free(ptr); }};class M2{public: static void *getMem(int size) { return malloc(size); } static void putMem(void *ptr) { return free(ptr); }};//this alloc class is just for the stl set<> allocatortemplate <typename T, typename M>class MyAllc : public allocator<T>{public: typedef size_t size_type; typedef typename allocator<T>::pointer pointer; typedef typename allocator<T>::value_type value_type; typedef typename allocator<T>::const_pointer const_pointer; typedef typename allocator<T>::reference reference; typedef typename allocator<T>::const_reference const_reference; pointer allocate(size_type _Count, const void* _Hint = NULL) { _Count *= sizeof(value_type); void *rtn = M::getMem(_Count); return (pointer)rtn; } void deallocate(pointer _Ptr, size_type _Count) { M::putMem(_Ptr); } template<class _Other> struct rebind { // convert this type to allocator<_Other> typedef MyAllc<_Other, M> other; }; MyAllc() throw() {} /*MyAllc(const MyAllc& __a) throw() : allocator<T>(__a) {}*/ template<typename _Tp1, typename M1> MyAllc(const MyAllc<_Tp1, M1>&) throw() {} ~MyAllc() throw() {}};int main(){ set<int, less<int >, MyAllc<int, M1> > set1; set<int, less<int >, MyAllc<int, M2> > set2; set1.insert(1); set2.insert(2); set1.erase(1); set2.erase(2);}
这种情况,模板参数是多参了,所以要注意rebind的实现,保证第二个参数不要变,而且,标准库使用rebind的时候,都是单参的,所以我们要提供的依旧是单参的版本,比如看看标准库的使用:
template<class _Ty,class _Alloc0>struct _Tree_base_types{// types needed for a container basetypedef _Alloc0 _Alloc;typedef _Tree_base_types<_Ty, _Alloc> _Myt; #if _HAS_CPP0Xtypedef _Wrap_alloc<_Alloc> _Alty0;typedef typename _Alty0::template rebind<_Ty>::other _Alty; #else /* _HAS_CPP0X */typedef typename _Alloc::template rebind<_Ty>::other _Alty; #endif /* _HAS_CPP0X */typedef typename _Get_voidptr<_Alty, typename _Alty::pointer>::type_Voidptr;typedef _Tree_node<typename _Alty::value_type,_Voidptr> _Node;typedef typename _Alty::template rebind<_Node>::other _Alnod_type;
三、进阶篇 (二)
对于模板多参数,可能有些人不能接受,所以,还有一种办法,对于特定的对象分配,使用不同的allocate版本,就可以对模板类成员函数做一个特化。
class M1{public: static void *getMem(int size) { return malloc(size); } static void putMem(void *ptr) { return free(ptr); }};class M2{public: static void *getMem(int size) { return malloc(size); } static void putMem(void *ptr) { return free(ptr); }};//this alloc class is just for the stl set<> allocatortemplate <typename T>class MyAllc : public allocator<T>{public: typedef size_t size_type; typedef typename allocator<T>::pointer pointer; typedef typename allocator<T>::value_type value_type;typedef typename allocator<T>::const_pointer const_pointer;typedef typename allocator<T>::reference reference;typedef typename allocator<T>::const_reference const_reference; pointer allocate(size_type _Count, const void* _Hint = NULL) { _Count *= sizeof(value_type); void *rtn = M1::getMem(_Count); return (pointer)rtn; } void deallocate(pointer _Ptr, size_type _Count) { M1::putMem(_Ptr); } template<class _Other> struct rebind {// convert this type to allocator<_Other> typedef MyAllc<_Other> other; }; MyAllc() throw() {} /*MyAllc(const MyAllc& __a) throw() : allocator<T>(__a) {}*/ template<typename _Tp1> MyAllc(const MyAllc<_Tp1>&) throw() {} ~MyAllc() throw() {}};template<>MyAllc<double>::pointer MyAllc<double>::allocate(size_type _Count, const void* _Hint){ _Count *= sizeof(value_type); void *rtn = M2::getMem(_Count); return (pointer)rtn;}template<>void MyAllc<double>::deallocate(pointer _Ptr, size_type _Count){ M2::putMem(_Ptr);}int main(){ MyAllc<double> aAllc; aAllc.allocate(1); aAllc.deallocate(NULL, 1); set<int, less<int >, MyAllc<int> > set1; set<double, less<double >, MyAllc<double> > set2; int a = 1; double b = 2; set1.insert(a); set2.insert(b); set1.erase(a); set2.erase(b);}
对于MyAllc<double> aAllc进行的allocate操作,都是使用的特化的,但是后面的set2.insert(b);,根本不会使用特化的内存分配器,为什么呢?呵呵,这个很简单了,set分配内存的单位不是double,而是RBTree_node<double>,所以不适用double特化的分配器。
- C++ STL 容器自定义内存分配器
- C++ STL 容器自定义内存分配器
- 分配器与STL容器
- STL容器默认的内存分配器(std::alloc)
- STL容器默认的内存分配器(std::alloc)
- STL容器默认的内存分配器(std::alloc)
- STL容器默认的内存分配器(std::alloc)
- STL容器默认的内存分配器(std::alloc)
- STL自定义分配器
- STL的内存分配器
- STL中的内存分配器
- STL的内存分配器
- STL的内存分配器
- STL内存分配器:allocator
- STL内存分配器
- STL的内存分配器
- STL内存分配器:allocator
- STL的内存分配器
- 五大机器视觉测量应用,彰显远心镜头技术优势
- django开发问题杂记
- Result analysis on Loading test use visual studio.
- 从网络得到图片数据保存到手机中,
- Oracle 12c 新特性之 Multitenant Architecture (五)
- C++ STL 容器自定义内存分配器
- 算法导论 Exercises 22.5
- Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core"
- Squid--hash代码分析
- 各种智能指针的介绍
- The Elements of Programming Style (编程风格的元素)读书总结
- 无法启动Eclipe,因找不到javaw.exe
- 实用技巧(1):eclipse配色插件
- 设计模式C++学习笔记之一(Strategy策略模式)