std::move and std::forward
These two library functions look like they do something dramatic, but each is just a carefully chosen cast — they generate no machine code of their own. std::move(x) says 'I am done with x, treat it as expendable so a move can happen', and std::forward<T>(x) says 'pass x onward keeping exactly whether the caller gave me a temporary or a named object'. Both are about steering which overload — copy or move — gets chosen.
std::move is the simpler one: it unconditionally casts its argument to an rvalue reference. That cast does not move anything; it merely makes the argument eligible to bind to a move constructor or move-assignment instead of a copy. If you have a named local you no longer need, std::move(local) lets the next operation pilfer it. std::forward is for generic 'forwarding' code. When a template takes an argument as T&& (a forwarding reference), the language lets that one parameter bind to both lvalues and rvalues; std::forward<T>(arg) then re-casts it back to its original value category as it is passed along, so a temporary stays move-able and a named object stays copy-able. This pattern — 'perfect forwarding' — is how make_unique and emplace_back pass your constructor arguments through untouched.
Why it matters: together they let library writers avoid needless copies and write one generic function that does the right thing for both temporaries and lvalues, instead of writing separate overloads. The honest pitfalls: after std::move(x) you must treat x as drained (valid but unspecified); std::forward is correct only inside a function whose parameter is a real forwarding reference T&& with a deduced T — using it elsewhere, or std::move on a const object, silently does nothing useful and you are back to a copy.
template<class... A> auto make(A&&... a) { return T(std::forward<A>(a)...); } // forwards each argument keeping its lvalue/rvalue-ness
Perfect forwarding: a temporary passed in stays move-eligible; a named lvalue stays copy-only — exactly as the caller intended.
std::move on a const object is a trap: it casts to const T&&, which a non-const move constructor cannot bind to, so the copy constructor is selected instead. You get a silent copy with no error — moving requires the source to be modifiable.