-
Notifications
You must be signed in to change notification settings - Fork 1
6.1 Allocators
Controlling allocation in standard library facilities.
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));
}
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;
}
}
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);
}
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);
}