Example
The example below defines a simple custom allocator. This can be used to test your compiler or the Standard C++ Library's support for custom allocators. It checks if the allocator argument that is passed in the code is actually used:
#include <rw/tvdlist.h>
#include <rw/cstring.h>
#include <iostream>
template <class T>
class my_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
my_allocator() {}
my_allocator(const my_allocator&) {}
pointer allocate(size_type n, const void * = 0) {
T* t = (T*) malloc(n * sizeof(T));
std::cout
<< " used my_allocator to allocate at address "
<< t << " (+)" << std::endl;
return t;
}
void deallocate(void* p, size_type) {
if (p) {
free(p);
std::cout
<< " used my_allocator to deallocate at address "
<< p << " (-)" <<
std::endl;
}
}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
my_allocator<T>& operator=(const my_allocator&) { return *this; }
void construct(pointer p, const T& val)
{ new ((T*) p) T(val); }
void destroy(pointer p) { p->~T(); }
size_type max_size() const { return size_t(-1); }
template <class U>
struct rebind { typedef my_allocator<U> other; };
template <class U>
my_allocator(const my_allocator<U>&) {}
template <class U>
my_allocator& operator=(const my_allocator<U>&) { return *this; }
};
int main()
{
const int numItems = 100;
std::cout << "\nCreating a RWTValDlist with a default allocator"
<< std::endl;
RWTValDlist<RWCString> regular;
std::cout << "\nInserting " << numItems
<< " items" << std::endl;
for (int i = 0; i < numItems; ++i) {
regular.insert(RWCString('a' + i, i));
}
std::cout << "\n\nCreating a RWTValDlist with my_allocator type"
<< std::endl;
RWTValDlist<RWCString, my_allocator<RWCString> > custom;
std::cout << "\nInserting " << numItems
<< " items\n" << std::endl;
for (int i = 0; i < numItems; ++i) {
custom.insert(RWCString('a' + i, i));
}
return 0;
}
Program Output
Creating a RWTValDlist with a default allocator
Inserting 100 items
Creating a RWTValDlist with my_allocator type
used my_allocator to allocate at address 0080ABD0 (+)
used my_allocator to allocate at address 0080AC08 (+)
Inserting 100 items
used my_allocator to allocate at address 0080AC40 (+)
used my_allocator to allocate at address 0080AC78 (+)
used my_allocator to allocate at address 0080C6F0 (+)
used my_allocator to allocate at address 0080C728 (+)
used my_allocator to allocate at address 0080FB28 (+)
used my_allocator to allocate at address 00820068 (+)
used my_allocator to deallocate at address 00820068 (-)
used my_allocator to deallocate at address 0080FB28 (-)
used my_allocator to deallocate at address 0080C728 (-)
used my_allocator to deallocate at address 0080C6F0 (-)
used my_allocator to deallocate at address 0080AC78 (-)
used my_allocator to deallocate at address 0080AC40 (-)
used my_allocator to deallocate at address 0080AC08 (-)
used my_allocator to deallocate at address 0080ABD0 (-)
In the output listed above, it can be seen that, when no custom allocator was used, the
RWTValDlist was created and 100 items were inserted. However, when the list was instantiated with
my_allocator, instances of this class were used in 8 allocations and deallocations of heap memory. This proves that the example used
my_allocator for memory management.