Move semantics

Core semantics7 standards

std::move discipline, elision, relocation.

Rvalue references, std::move, std::forward. Core discipline: moved-from objects are valid-but-unspecified; move constructors should be noexcept or containers will copy.

Buffer(Buffer&& other) noexcept
  : data_(std::exchange(other.data_, nullptr)),   // exchange is C++14
    size_(std::exchange(other.size_, 0)) {}

std::exchange lands (the one-liner for move constructors above), and init-captures move state into lambdas: [b = std::move(buf)].

Guaranteed copy elision: prvalues are initializations, not objects. Consequence: return x; is right and return std::move(x); on a local is a pessimization that blocks NRVO.

Widget make() {
  Widget w;
  w.configure();
  return w;            // NRVO or implicit move — never std::move here
}

P1825 widens implicit move: more returns of local variables and parameters (including rvalue-reference parameters) move automatically; another class of std::move calls becomes noise.

P2266 simplifies the implicit-move rules further, and auto(x) gives an explicit decay-copy in generic code. std::move_only_function finally stores move-only callables.

template <class R>
void take_snapshot(R&& range) {
  process(auto(std::forward<R>(range)));  // explicit copy, intent visible
}

Trivial relocation (P2786): std::is_trivially_relocatable plus trivially_relocate let containers grow by memcpy instead of move+destroy pairs — move semantics meets its performance endgame.

static_assert(std::is_trivially_relocatable_v<SmallString>);
// vector reallocation: one memcpy for the whole block, no per-element moves
C++29direction · not adopted

Direction: library adoption of relocation (vector, inplace_vector optimizations) and the long-running destructive-move discussions continue.

C++26 per the final working draft; C++29 rows are proposals and direction, not adopted features.