如何获得std :: map的真正分配器?

时间:2014-09-18 18:06:03

标签: c++ map stl allocator

我想打印STL地图容器的自定义内存分配器的工作结果。我想打印内存分配图。
我有get_allocator()的问题。见例子 get_allocator()调用为初始pair<int,int>提供分配器。它甚至创造了它......

有没有办法获得真正的分配器(Pool的实例RBtree),它为地图的元素提供了内存?

我正在使用gcc。感谢。

#include <memory>
#include <map>
using namespace std;
class Pool {
  //...
public:
  Pool(unsigned n);
  ~Pool();
  void* alloc();  
  void free(void*);
  void print_mm();  //print pool map
  //...
};
void* Pool::alloc() {
  //...
}
//...
void Pool::print_mm() {
  //...
}
template<class T> class Pool_alloc : public allocator<T> {
  static Pool pool;
public:
  template<class U> struct rebind {
    typedef Pool_alloc<U> other;
  };
  template<class U> Pool_alloc(const Pool_alloc<U>&) {}
  Pool_alloc() {}
  T* allocate(size_t, void*);
  void deallocate(T*, size_t);
  void print_mm() {pool.print_mm();}
};
template<class T> Pool Pool_alloc<T>::pool(sizeof(T));
template<class T> T* Pool_alloc<T>::allocate(size_t n, void* = 0) {
   //...
   return p;
}
template<class T> void Pool_alloc<T>::deallocate(T* p, size_t n) {
   //...
}
main() {
  map<int, int, less<int>, Pool_alloc<pair<int, int> > > m;
  m[144] = 12;
  m.get_allocator().print_mm();  //doesn't work - it gives the wrong allocator :-(
}

接下来是示例的完整代码 - 它的基础取自着名的Bjarne Stroustrup的书。 ; - )

#include <iostream>
#include <memory>
#include <map>
using namespace std;
class Pool {
   struct Link {Link *next;};
   struct Chunk {
      static const unsigned size = 8192 - sizeof(Chunk*); //page boundary
      Chunk *next;
      char mem[size];
   } *chunks;
   Link *head;  //pointer to first free link
   Pool(Pool&);  //disable
   void operator=(Pool&); //disable
   void grow();
public:
   const unsigned int atomsize;
   Pool(unsigned n);  //n - number of atoms
   ~Pool();
   void* alloc();  //for one atom
   void free(void*);
   void print_mm();  //print pool memory map
};
void* Pool::alloc() {
   if (head == 0) grow();
   Link *p = head;
   head = p->next;
   return p;
}
void Pool::free(void *b) {
   Link *p = static_cast<Link*>(b);
   p->next = head;
   head = p;
}
Pool::Pool(unsigned sz): atomsize(sz < sizeof(Link*) ? sizeof(Link*) : sz) {
   cout << "atom size = " << atomsize << " bytes\n";
   head = 0;
   chunks = 0;
}
Pool::~Pool() {
   Chunk *p = chunks;
   while (p) {
      Chunk *q = p;
      p = p->next;
      delete q;
   }
}
void Pool::grow() {
   Chunk *p = new Chunk;
   p->next = chunks;
   chunks = p;
   const unsigned noe = Chunk::size/atomsize;
   char *start = p->mem, *last = start + (noe - 1)*atomsize;
   for (char *p = start; p < last; p += atomsize)
      ((Link*)p)->next = (Link*)(p + atomsize);
   ((Link*)last)->next = 0;
   head = (Link*)start;
}
void Pool::print_mm() {
   cout << "The pool memory map\n";
   ///...
}
template<class T> class Pool_alloc : public allocator<T> {
   static Pool pool;  //static for STL
public:
   template<class U> struct rebind {
      typedef Pool_alloc<U> other;
   };
   template<class U> Pool_alloc(const Pool_alloc<U>&) {}
   Pool_alloc() {}
   T* allocate(size_t, void*);
   void deallocate(T*, size_t);
   static void print_mm() {pool.print_mm();}
};
template<class T> Pool Pool_alloc<T>::pool(sizeof(T));
template<class T> T* Pool_alloc<T>::allocate(size_t n, void* = 0) {
   T* p;
   if (n == 1)
      p = static_cast<T*>(pool.alloc());
   else
      p = static_cast<T*>(allocator<T>::allocate(n));    //STL level
      //p = static_cast<T*>(operator new (sizeof(T)*n));  //OS level
   return p;
}
template<class T> void Pool_alloc<T>::deallocate(T* p, size_t n) {
   if (n == 1)
      pool.free(p);
   else
      allocator<T>::deallocate(p, n);  //STL level
      //operator delete(p);  //OS level
}
main() {
   map<int, int, less<int>, Pool_alloc<pair<int, int> > > m;
   m.insert(pair<int,int>(7, 8));
   for (int i(0); i < 200; ++i)
      m[i*i] = 2*i;
   m.erase(169);
   m.erase(121);
   m[5] = 88;
   cout << m[7] << '-' << m[5] << '-' << m.size() << endl;
   m.get_allocator().print_mm();  //doesn't work - it gives the wrong allocator :-(
}

1 个答案:

答案 0 :(得分:1)

试试这个:

template<class T, Pool* pool> class Pool_alloc : public allocator<T> {
public:
  template<class U> struct rebind {
    typedef Pool_alloc<U, pool> other;
  };

这需要您提供不同大小的Pool支持数据。

或者,将Pool替换为Pool<sizeof(T)>,也许使用static方法技巧来分配单例实例,然后您至少可以查找各种大小的分配器。 (他们可以在全球池中注册,以便您以后可以找到它们。)

您的池分配器可以足够智能,以便为请求的不同大小的数据使用不同大小的块。或者不,如你所愿。