When I need to make an std::vector
from some elements of another container, e.g. another vector, the safest way to ensure that the new vector will be allocated in memory only once is:
std::vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
const size_t amount = 3;
std::vector<int> v2;
v2.reserve(amount);
v2.insert(v2.begin(), v1.begin(), v1.begin() + amount);
Meanwhile this code is much longer than very simple constructions from Best way to extract a subvector from a vector like
std::vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
const size_t amount = 3;
std::vector<int> v2(v1.begin(), v1.begin() + amount);
or
std::vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
const size_t amount = 3;
std::vector<int> v2 = {v1.begin(), v1.begin() + amount};
The questions is: do the latter cases ensure that memory for v2
will be allocated only once or the specific implementation could easy use something like cycle of push_back()
or emplace_back()
and lead to many container memory reallocation during its creation as a copy?
Is is guaranteed by the standard or at least can I rely on existing implementations that they won't reallocate memory many times?
I am concerned because I work with huge containers and want to make sure this more readable code won't have performance impact.
I found this passage in the C++23 standard:
24.3.11.2 Constructors [vector.cons]
template<class InputIterator> constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
- Effects: Constructs a
vector
equal to the range[first, last)
, using the specified allocator.- Complexity: Makes only N calls to the copy constructor of T (where N is the distance between first and last) and no reallocations if iterators first and last are of forward, bidirectional, or random access categories. It makes order N calls to the copy constructor of T and order log N reallocations if they are just input iterators.
That means a conforming implementation will do it as least as efficiently as your manual call to reserve
+ insert
.