Which allocator is used when allocating a nested STL container?
allocator, c++, dictionary, stl, vector
Solution
Your question is related to the Scoped Allocator Model, which is a style of allocator design that automatically propagates a container's allocator to the container's elements, so that you can ensure all a container's elements are allocated from the same allocator. More on that below.
To answer your question:
1) Containers do not use the scoped allocator model by default, you have to request it explicitly (see `scoped_allocator_adaptor` below)
2) Your nested container is type `std::vector<int>` which means it uses the default `std::allocator<int>` allocator, and all instances of that type are equal, so the answer to your question is that it uses the standard allocator - it doesn't matter which one, because every `std::allocator<int>` is the same.
The rest of this answer is just a thought experiment, the answer to your question is above: `vector<int>` always uses `std::allocator<int>`
Now, if your nested type was `std::vector<int, A1<int>>` where `A1<int>` is a custom allocator the question gets more interesting.
The nested container will use the allocator it's constructed with, and you haven't shown that because you've said "assuming an entry exists for `mapInstance[0]`" and how that entry is created is what determines what allocator it will use.
If that entry is created like this:
mapInstance[0];
then the entry is default-constructed and will use a default-constructed `A1<int>`.
If that entry is created like this:
A1<int> a1( /* args */ );
myvect v(a1)
mapInstance.insert(mymap::value_type(0, v));
then the entry will be a copy of `v` and in C++03 its allocator will be a copy of `v.get_allocator()`, but in C++11 its allocator will be a copy of `std::allocator_traits<A1<int>>::select_on_container_copy_construction(v.get_allocator())`, which might be a copy of `v.get_allocator()` but might be something different (e.g. a default-constructed `A1`.)
(In C++03 the entry's allocator cannot be changed after it's created, so the answer would end here, but in C++11 it can be replaced. I assume we're talking C++11 for the rest of this question, because allocators are not very interesting in C++03.)
If that entry is modified like this:
A1<int> a1( /* args */ );
myvect v(a1)
mapInstance[0] = v;
then the vector gets copy-assigned to, which might replace the allocator, depending on the value of `std::allocator_traits<A1<int>>::propagate_on_container_copy_assignment::value`
If that entry is modified like this:
A1<int> a1( /* args */ );
mapInstance[0] = myvect(a1);
then the vector gets move-assigned to, which might replace the allocator, depending on the value of `std::allocator_traits<A1<int>>::propagate_on_container_move_assignment::value`
If that entry is modified like this:
A1<int> a1( /* args */ );
myvect v(a1)
swap( mapInstance[0], v );
then the vector gets swapped, which might replace the allocator, depending on the value of `std::allocator_traits<A1<int>>::propagate_on_container_swap::value`
Now, if `A` is `std::scoped_allocator_adaptor<A1<std::pair<const int, myvect>>>` things get even more interesting! The `scoped_allocator_adaptor` is, as its name suggests, an adaptor, which allows any allocator type to be used with the Scoped Allocator Model which means that a container's allocator can be passed to the container's children, and to its children's children, etc. (as long as those types use allocators and can be constructed with them.)
By default containers and allocators do not use the scoped allocator model you need to use `scoped_allocator_adaptor` (or write your own allocator type that works the same) to use it. (And C++03 has no support at all for scoped allocators.)
If that entry is created like this:
mapInstance[0];
then instead of the entry being default-constructed the `scoped_allocator_adaptor` will construct it with a copy of the map's allocator, so the entry will be constructed like `myvect( A1<int>(mapInstance.get_allocator()) )`.
If that entry is created like this:
A1<int> a1( /* args */ );
myvect v(a1)
mapInstance.insert(mymap::value_type(0, v));
then the entry will have a copy of `v`'s data, but will not use its allocator, instead it will be passed an allocator by the `scoped_allocator_adaptor`, so will be constructed like: `myvect( v, A1<int>(mapInstance.get_allocator()) )`.
If that's all a bit confusing, welcome to my world, but don't worry, in your case `vector<int>` will always use `std::allocator<int>`.
Problem
I have a question about STL classes and allocators that doesn't seem to be easy to find online. Does anyone know which allocator is used in a nested STL class? For example: ``` typedef std::vector<int> myvect; ``` //the line below was edited as pointed out by subsequent replies/comments ``` typedef std::map<int, myvect, std::less<int>, A> mymap; //uses my custom allocator for map creation ``` Let's call the default allocator `D`, and assume I have a custom allocator `A`. What would happen if I did the following: Create a map: ``` mymap mapInstance; ``` Now, assuming an entry exists for `mapInstance[0]`, suppose I push a value into the vector: ``` mapInstance[0].push_back(999); ``` What allocator is used for the dynamic memory of the vector `mapInstance[0]`? My understanding so far is that the default allocator `D` is used, but I want to confirm that the custom allocator `A`, which was passed to the map, is not instead used. (As far as I know, this would only happen were I to use some sort of nested allocation option.) I understand, of course, that the metadata/header info for `mapInstance[0]` is allocated using the custom allocator `A`. What I'm concerned about is the dynamic memory part, that is, the part after `d_dataBegin`.