DESCRIPTION

Heap allocators are generally used when there is a lot of allocation and deallocation of small objects. For instance, this is often the case when dealing with std::list and std::map.

Heap-based allocator is conform to the STL specification of allocators. It does not "free" the memory until the heap is destroyed.

This allocator handles an a priori unlimited area of memory: a sequence of growing chunks are allocated. For a limited memory handler in the same spirit, see "stack_allocator"(9).

EXAMPLE

    typedef map <size_t, double, less<size_t>, heap_allocator<pair<size_t,double> > >  map_type;
    map_type a;
    a.insert (make_pair (0, 3.14));
    a.insert (make_pair (1, 1.17));
    for (map_type::iterator iter = a.begin(), last = a.end(); iter != last; iter++) {
      cout << (*iter).first << " " << (*iter).second << endl;
    }

IMPLEMENTATION

template <typename T>
class heap_allocator {
protected:
    struct handler_type; // forward declaration:
public:

// typedefs:

    typedef size_t         size_type;
    typedef std::ptrdiff_t difference_type;
    typedef T*             pointer;
    typedef const T*       const_pointer;
    typedef T&             reference;
    typedef const T&       const_reference;
    typedef T              value_type;

// constructors:

    heap_allocator() throw()
      : handler (new handler_type)
    {
    }
    heap_allocator (const heap_allocator& ha) throw()
      : handler (ha.handler)
    {
        ++handler->reference_count;
    }
    template <typename U>
    heap_allocator (const heap_allocator<U>& ha) throw()
      : handler ((typename heap_allocator<T>::handler_type*)(ha.handler))
    {
        ++handler->reference_count;
    }
    ~heap_allocator() throw()
    {
        check_macro (handler != NULL, "unexpected null mem_info");
        if (--handler->reference_count == 0) delete handler;
    }
    // Rebind to allocators of other types
    template <typename U>
    struct rebind {
        typedef heap_allocator<U> other;
    };

// assignement:

    heap_allocator& operator= (const heap_allocator& ha)
    {
        handler = ha.handler;
        ++handler->reference_count;
        return *this;
    }

// utility functions:

    pointer       address (reference r)       const { return &r; }
    const_pointer address (const_reference c) const { return &c; }
    size_type     max_size() const { return std::numeric_limits<size_t>::max() / sizeof(T); }

// in-place construction/destruction

    void construct (pointer p, const_reference c)
    {
        // placement new operator:
        new( reinterpret_cast<void*>(p) ) T(c);
    }
    // C++ 2011: default construct a value of type T at the location referenced by p
    void construct (pointer p) { new ( reinterpret_cast<void*>(p) ) T(); }

    void destroy (pointer p)
    {
        // call destructor directly:
        (p)->~T();
    }

// allocate raw memory

    pointer allocate (size_type n, const void* = NULL)
    {
        return pointer (handler->raw_allocate (n*sizeof(T)));
    }
    void deallocate (pointer p, size_type n)
    {
        // No need to free heap memory
    }
    const handler_type* get_handler() const {
        return handler;
    }

// data:

protected:
    handler_type* handler;
    template <typename U> friend class heap_allocator;
};