In the C++11 standard we have std::scoped_allocator_adaptor
in the dynamic memory management library. What are the most important use cases of this class?
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Why does const allow implicit conversion of refere
- thread_local variables initialization
- What uses more memory in c++? An 2 ints or 2 funct
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Selecting only the first few characters in a strin
- What exactly do pointers store? (C++)
- Override env values defined in container spec
- Converting glm::lookat matrix to quaternion and ba
Say you have a stateful arena allocator
Alloc
with a constructorAlloc(Arena&)
that allows some special performance for your application, and say that you use a nested hierarchy of containers like this:Here, the use of
scoped_allocator_adaptor
will let you propagate the arena object used to initialize your allocator from the outer to the inner container like this:This achieve greater data locality and lets you pre-allocate one big memory arena
my_arena
for your entire container hierarchy, rather than only makemy_arena
available for the outer container, and requiring a loop over all innner containers with another arena for each element at that level.The class template is actually a variadic template that gives you fine-grained control about which type of allocator to use in each type of the container hierarchy. Presumably this gives complicated data structures better performance (I must confess I haven't seem different allocators in different levels in action anywhere, but maybe large data centers with multi-million users have a use case here).
If you want a container of strings and want to use the same allocator for the container and its elements (so they are all allocated in the same arena, as TemplateRex describes) then you can do that manually:
However, this is awkward and error-prone, because it's too easy to accidentally insert a string which doesn't use the same allocator:
The purpose of
std::scoped_allocator_adaptor
is to automatically propagate an allocator to the objects it constructs if they support construction with an allocator. So the code above would become:Now the vector's allocator is automatically used to construct its elements, even though the objects being inserted,
String("hello")
andString("world")
, are not constructed with the same allocator. Sincebasic_string
can be implicitly constructed fromconst char*
the last two lines can be simplified even further:This is much simpler, easier to read, and less error-prone, thanks to
scoped_allocator_adaptor
constructing the elements with the vector's allocator automatically..When the vector asks its allocator to construct an element as a copy of
obj
it calls:Normally the allocator's
construct()
member would then call something like:But if the
allocator_type
isscoped_allocator_adaptor<A>
then it uses template metaprogramming to detect whethervalue_type
can be constructed with an allocator of the adapted type. Ifvalue_type
doesn't use allocators in its constructors then the adaptor does:And that will call the nested allocator's
construct()
member, which uses something like placement new, as above. But if the object does support taking an allocator in its constructor then thescoped_allocator_adaptor<A>::construct()
does either:or:
i.e. the adaptor passes additional arguments when it calls
construct()
on its nested allocator, so that the object will be constructed with the allocator. Theinner_allocator_type
is another specialization ofscoped_allocator_adaptor
, so if the element type is also a container, it uses the same protocol to construct its elements, and the allocator can get passed down to every element, even when you have containers of containers of containers etc.So the purpose of the adaptor is to wrap an existing allocator and perform all the metaprogramming and manipulation of constructor arguments to propagate allocators from a container to its children.