2014-09-18 54 views
2

我想打印STL地图容器的自定义内存分配器的工作结果。我想要打印内存分配图。
我有一个get_allocator()的问题。看例子。
get_allocator()调用给出分配器初始的pair<int,int>。它甚至创建它...如何获得std :: map的真正分配器?

有没有一种方法来获得真正的分配器(PoolRBtree的实例),它为地图元素提供内存?

我正在使用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 :-(
} 
+0

你的意思是'rebind'? – Yakk 2014-09-18 18:11:16

+0

print_mm()打印由Pool类分配的内存。 Pool类由Pool_alloc使用。分配器工作正常。我只是在寻求一种方法来访问它。 – vollitwr 2014-09-18 18:36:50

+0

从'Pool'的析构函数调用'print_mm',也许? – Casey 2014-09-18 18:53:20

回答

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<sizeof(T)>取代Pool,也许使用static方法把戏分配单个实例,那么你至少可以找到各种大小的分配器。 (他们可以在全球池中注册,以便稍后可以找到它们)。

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

+0

谢谢。但是......你能给我提供更多提示吗?我将所有代码放在上面...... Pool类支持任何大小的数据,直到达到固定的最大值。 – vollitwr 2014-09-19 02:57:52