Adrian
Adrian

Reputation: 10911

How does an allocator work with std::vector?

I was looking at the documentation for vector::vector on cppreference, and as an exercise, was trying to figure out how I'd implement explicit vector( const Allocator& alloc ) noexcept;

The question I found asking myself was, why would you pass an Allocator to the vector? It would only make sense if the Allocator was polymorphic. However, if that group of allocators have different state info, i.e. have different sizes, this causes the following issues:

  1. You can't just have a allocator as a member/base class, as you would cause the object to be sliced when copied.
  2. If you don't have it as a member, it would have to be allocated. Allocation implies that it can cause an exception.

So, given those reasons, does that mean that the group of allocators must have state only in the base class? Is there anything else that I'm missing?

Upvotes: 2

Views: 2294

Answers (1)

Sam Varshavchik
Sam Varshavchik

Reputation: 118300

If you don't have it as a member, it would have to be allocated. Allocation implies that it can cause an exception.

No, it doesn't have to be allocated. To construct an instance of std::vector it only needs to be copy-constructed.

The allocator instance gets passed as a const reference to std::vector's constructor. The std::vector itself has an instance of Allocator as a (private) class member, and it is copy-constructed from this parameter.

Keep in mind that Allocator is the second (defaulted) std::vector template parameter. As such, a typical implementation declares Allocator as a (private) member of std::vector itself, so the only allocation that occurs is the allocation of std::vector itself.

The default constructor of std::vector default-constructs its Allocator class member, which is also noexcept (as of C++17).

So the capsule summary is that the allocator class (as of C++17) must have a noexcept copy constructor, and a noexcept default constructor, it order to meet the noexcept exception requirement of std::vector itself.

There is no requirement for additional allocation to occur as part of constructing an instance of std::vector (for constructors that don't initialize the contents of std::vector as part of its construction) -- excepting the allocation of the std::vector itself.

Upvotes: 2

Related Questions