Skip to content
Glen Fernandes edited this page May 15, 2013 · 4 revisions

Controlling allocation in standard library facilities.

How do I use an allocator with C++ standard library containers?

Assume you have a stateful allocator that you want to use in standard library containers.

class CustomAllocator {
public:
    void* Allocate(std::size_t size);
    void  Free(void* memory);
};

C++11 simplified writing allocator adapter types requiring you to provide less members. Use a shared pointer instead of a raw pointer when sharing semantics are required.

template<typename T>
class Allocator {
public:
    typedef T value_type;
    Allocator(CustomAllocator& state_) noexcept 
        : state(&state_) {
    }    
    template<typename U>
    Allocator(const Allocator<U>& other) noexcept
        : state(other.state) {
    }
    T* allocate(std::size_t count) {
        return static_cast<T*>(state->Allocate(count * sizeof(T)));
    }
    void deallocate(T* memory, std::size_t) {
        state->Free(memory);
    }
    template<typename U>
    bool operator==(const Allocator<U>& other) noexcept {
        return state == other.state;
    }
    template<typename U>
    bool operator!=(const Allocator<U>& other) noexcept {
        return !(*this == other);
    }
private:
    CustomAllocator* state;
};

Using the allocator with a standard library container is easy:

void sample(CustomAllocator& state) {
    std::vector<int, Allocator<int> > vector(Allocator<int>(state));
}

How do I use an allocator to allocate and construct an object?

Rebind the allocator to the given type and use that instance for allocation and deallocation.

template<typename Type, typename... Arguments, typename Allocator>
Type* sample(const Allocator& allocator, Arguments&&... arguments) {
    Type* memory = std::allocator_traits<Allocator>::allocate(allocator, 1);
    try {
        std::allocator_traits<Allocator>::construct(allocator, memory, std::forward<Arguments>(arguments)...);      
        return memory;
    } catch (...) {
        std::allocator_traits<Allocator>::deallocate(allocator, memory, 1);
        throw;
    }
}

How do I efficiently allocate shared objects with an allocator?

Both Boost and the standard C++ library provide utilities to allocate a shared object:

template<typename Type, typename Allocator>
void sample(const Allocator& allocator) {
    std::shared_ptr<Type> object = std::allocate_shared<Type>(allocator);
}

The Boost equivalent of the above:

template<typename Type, typename Allocator>
void sample(const Allocator& allocator) {
    boost::shared_ptr<Type> object = boost::allocate_shared<Type>(allocator);
}

How do I efficiently allocate shared arrays with an allocator?

This is only possible with Boost (since 1.53). You can use shared pointers with array types and get shared pointers of arrays with a single allocation.

template<typename Type, typename Allocator>
void sample(const Allocator& allocator, std::size_t count) {
    boost::shared_ptr<Type[]> array = boost::allocate_shared<Type[]>(allocator, count);
}

This can also be used with an array of fixed size.

template<typename Type, std::size_t N, typename Allocator>
void sample(const Allocator& allocator) {
    boost::shared_ptr<Type[N]> array = boost::allocate_shared<Type[N]>(allocator);
}

How do I control allocation of elements in nested containers?

Clone this wiki locally