🔑Go deeper — read the bookC++ Keywords by Version — Specifiers & Attributes— runnable code & full walkthrough →📦Go deeper — read the bookstd::vector, from the inside— runnable code & full walkthrough →

cpp core · high

noexcept Moves & Vector Growth

When a std::vector grows, it allocates a larger buffer and must transfer the existing elements. It would prefer to move them, but reallocation has to provide the strong exception guarantee: if a transfer threw partway through, vector must be able to leave the original intact. So it uses std::move_if_noexcept — it moves an element only if that element's move constructor is noexcept, and otherwise falls back to copying (a copy leaves the source untouched, so a throw can be rolled back). A noexcept move ctor therefore makes every reallocation an O(n) sequence of cheap pointer steals, while a move ctor that might throw silently turns each growth into O(n) deep copies plus allocations. Mark move constructors and move assignment operators noexcept (and ensure they truly cannot throw) so the standard containers take the fast path.

🔑 Key line

Vector reallocation uses std::move_if_noexcept, so it moves elements only when their move constructor is noexcept and otherwise deep-copies them to preserve the strong exception guarantee — always mark move ctor and move assignment noexcept so containers move, not copy.

The code

struct Buf {
Buf(Buf&& o) noexcept; // noexcept move -> vector will MOVE
// Buf(Buf&& o); // throwing move -> vector falls back to COPY
Buf(const Buf& o); // deep copy (the expensive fallback)
~Buf();
};
std::vector<Buf> v; // grows by reallocation when full
v.push_back(x); // capacity exceeded -> reallocate:
// allocate a bigger buffer, then transfer the elements
// move_if_noexcept: MOVE if the move ctor is noexcept, else COPY

What this lesson walks through

  1. 01A full vector must reallocate
  2. 02Move or copy? move_if_noexcept decides
  3. 03noexcept move → steal the resources
  4. 04Move done: fast and allocation-free
  5. 05Throwing move → vector won't risk it
  6. 06Copy done: the hidden cost
  7. 07Mark your moves noexcept

v holds 4 Buf elements and is at capacity. The next push_back needs more room, so vector allocates a larger buffer and must transfer the existing elements into it.

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of noexcept Moves & Vector Growth and 100+ animated C++ interview lessons.

← Previous
RVO & Copy Elision
Next →
How shared_ptr Ref-Counting Works