9

With the latest trends about C and C++ applications, and with latest I mean the latest years, I was expecting to see std::allocators to be used way more frequently than what it really is.

Modern applications are usually multithreaded or with form of concurrency in them, and they manage a significant amount of memory, especially in some fields like games and multimedia applications; so the usual high cost of the allocation/deallocations rises and impacts the performances even more than in old applications.

But for what I can see this kind of memory management through std::allocators is not popular, I can't even count 1 library that I know of, that is using any rationale about a standardize way of managing memory.

There is a real reason why std::allocator is not popular ? Technical reasons ?

6
  • 3
    because it is hard to use?
    – Bryan Chen
    May 6, 2014 at 1:14
  • 4
    @BryanChen what do you mean with that ? the allocator is usually the 2nd argument in any standard container, std::allocator it's extremely easy to use. May 6, 2014 at 1:17
  • 1
    Are you asking why std::allocator (which is basically a wrapper around new and placement-new) isn't used as much? Or are you asking why the C++ concept of Allocator isn't widley used? They're two different questions.
    – Dave S
    May 6, 2014 at 1:17
  • @DaveS more like the first option, but I don't understand why it differs from the 2nd one, you mean something related to the portability of the code itself ? May 6, 2014 at 1:19
  • 1
    @BryanChen can you show why it's hard ? what are the pitfalls ? May 6, 2014 at 1:21

3 Answers 3

13

There are sort of two questions here:

1) Why isn't std::allocator used more?

The short answer is because for most uses, using new and delete is sufficient.

First, a brief overview of what the C++11 Allocator concept is intended for. Basically, when you do a new Foo, it both allocates memory and then constructs the object in that memory.

But what if you needed to allocate memory and construct as two separate steps. The classic example of this is std::vector, which can allocate memory without initializing it immediately, but then constructs the elements as you add them to the container. The point of std::allocator is to provide an interface for doing those separate steps in a uniform way.

However, for most users, they don't need that level of control, because it's just another thing to remember to do when cleaning up your exceptions.

2) Why don't more things make use of the C++ concept of Allocator?

Mostly the need isn't there. The only classes that tend to use them are the ones that want to give their users more control over the source of the memory they allocate. The Standard library containers are written that way so that the user can make those decisions if they choose, but they default to using the normal allocator.

1
  • 3
    +1 for point 1 which is the real reason in my opinion. Not "it is hard to use" which I completely disagree having written many memory allocators for various memory pools: the allocator is quite easy to write and it's just an interface-conformant series of methods. How you manage the memory is up to you, can be easy or can be hard (chunking with coalescing mechanisms)
    – Marco A.
    May 6, 2014 at 7:46
6

The popularity of a language or a library concept is in an inverse correlation with its underlying complexity.

The std::allocator is a low level concept and as such has potential pitfalls. Having a custom allocator upfront is likely to be judged a premature optimisation. Further, similarly to other low level concepts, it is generally preferred to delegate the work allocation management to libraries (stdlib, boost) unless the overhead of handling the complexity of your own allocations is absolutely warranted.

Consider pointers as just one supporting example of this thesis. We love pointers for their unfetterred access to memory and zero overhead, but in C++ we know better to use scoped/raii wrappers to manage the complexity, that is until we explicitly need the performance or can all agree on some non-owning semantics for certain well-defined use-cases.

When using an std::allocator you need to consider the ABI and the API compatibilities, and wonderful question such as the desired behaviour when the code is engaging
std::vector<T,A1>().swap(std::vector<T,A2>()) with different (and stateful!) A1 and A2 allocators. Further, some containers don't even use the allocator in the way you intended! Take a look at std::list<T,A> or std::map<K,T,C,A> for example. The natural expectation is for the allocator to be used to allocate objects of type T for a list or a pair<const K,T> for a map, however in practice a standard library implementation will asks to allocate a list or map node, and even the size of the node can be different between release and debug builds. Custom allocators are rife with minutia, and the added complexity and detail is unnecessary for the most common programming tasks.

2
  • What is the overhead of using the RAII wrapper std::unique_ptr<T> to own memory as opposed to T *? Oct 11, 2015 at 2:00
  • @DavidStone As I'm guessing you already knew (making that a trick question), the answer is zero. Mar 19, 2017 at 18:56
2

An allocator is a dependency-injected policy, into the standard containers. It is there mostly to allow client code to separate allocation policy from instantiation, in already implemented containers.

The problem appears when you need to use std:: containers, and the default allocation policy (as implemented by std::allocator) doesn't suit the needs of your project (e.g. you want the std::vector implementation to throw if more than 1024 objects are allocated, you want to use a memory pool, or ensure the allocations are all preallocated in a certain memory area and so on).

If you could not inject a different allocator into the containers, this would prohibit you from using the std::containers alltogether in some projects.

To get around this (and ensure you can still use the std:: containers when you have complex memory requirements), the allocator is a templated parameter for the containers.

To answer your question: most people don't use std::allocators because when they write client code they have full control of the allocations - so they don't need to inject an allocation policy - and when they use library code, the std::allocator is usually enough.

Not the answer you're looking for? Browse other questions tagged or ask your own question.