Skip to content

← Containers, Strings, Algorithms step 1 of 5

Easy Primitives

Reserve space before filling a vector

A vector has a size, the number of elements it contains, and a capacity, the number it can hold before it needs more storage. Appending beyond its capacity allocates a larger buffer and relocates the existing elements. Reallocation invalidates pointers, references and iterators into the old storage.

A sequence of push_back calls has amortized constant cost per insertion: although an individual insertion can relocate many elements, the total work for n insertions grows as O(n). Implementations typically grow capacity geometrically; C++ does not prescribe a particular growth factor.

For illustration, a vector whose capacity doubles could grow like this:

New capacity Existing elements relocated
1 0
2 1
4 2
8 4

That schedule relocates seven existing elements while inserting eight. Relocation may move or copy elements depending on their type. The Item provided in this exercise has a noexcept move constructor, so vector growth can use it without risking an exception from the move.

Reserve capacity before inserting

std::vector<Item> out;
out.reserve(n);

After a successful reserve(n), capacity is at least n. Size is still zero. Appending up to that capacity needs no further reallocation. Reserving on an already populated vector can itself relocate elements if more space is needed; a request within the current capacity does nothing.

If you know the final count, reserving once avoids the intermediate growth steps. You can also reserve a reasonable upper bound, at the cost of unused capacity. Do not call reserve(size() + 1) before every insertion: repeatedly requesting just enough space can defeat geometric growth.

Reserve and resize do different jobs

Operation Size afterwards Effect on elements
reserve(n) Unchanged May relocate existing elements; adds none
resize(n) n Adds elements when growing, removes them when shrinking

For an empty vector of this exercise's Item, resize(n) creates n default items. Appending another n items afterwards would leave 2n elements. Use reserve when making room for appends. Use resize when you want elements to exist so that you can assign by index.

emplace_back can construct an element from its constructor arguments, but it does not prevent reallocation when capacity is exhausted. shrink_to_fit requests less unused capacity; the implementation may ignore that request.

Your task

std::vector<Item> filtered(std::vector<Item>& items, int threshold);

Move every item with value >= threshold into a new vector in input order. Preserve each selected item's payload. Keep the size of items unchanged and leave unselected elements untouched. Leave the provided Item type unchanged.

Its counters must report exactly one move per selected item and zero copies during filtered. The starter selects the right values but can make extra moves as the output vector grows. Prepare enough capacity before inserting.

For values [1, 5, 2, 8, 9, 3] and threshold 5, return items with values [5, 8, 9], with zero copies and three moves. If none qualify, return an empty vector with both counters still zero. The harness reports values and counters; it does not display payloads or the source vector.