Copy and Move Semantics¶
Copying creates an independent value according to a type's contract. Moving allows a new object to reuse resources from an object that is no longer needed in its current state.
Special member functions¶
A class can have a destructor, copy constructor, copy assignment, move constructor, and move assignment. User-declaring some of them affects implicit generation of others. Prefer the Rule of Zero by composing resource-managing members.
class document {
public:
document(std::string title, std::vector<std::string> lines)
: title_{std::move(title)}, lines_{std::move(lines)} {}
private:
std::string title_;
std::vector<std::string> lines_;
}; // compiler-generated copy and move operations are appropriate
std::move does not move¶
std::move(expression) casts its argument to an xvalue, enabling overload
resolution to select move operations. The selected constructor or function
performs the actual transfer.
After a move, standard-library objects are generally valid but in an unspecified state unless a stronger contract is stated. They may be destroyed or assigned; do not assume they are empty.
Copy elision¶
Returning a local value is normally clear and efficient:
Guaranteed copy-elision cases and named return-value optimization avoid many
copies. Writing return std::move(result); can inhibit NRVO and is usually not
an optimization.
Resource-owning type¶
If a class owns a non-RAII handle directly, the Rule of Five prompts review of all special operations. A common policy is movable but not copyable:
class file_handle {
public:
file_handle(file_handle const&) = delete;
file_handle& operator=(file_handle const&) = delete;
file_handle(file_handle&& other) noexcept;
file_handle& operator=(file_handle&& other) noexcept;
~file_handle();
};
Move operations should leave both objects destructible and assignable. Marking a
move constructor noexcept when truthful enables containers to preserve strong
exception guarantees during reallocation.
Forwarding¶
Perfect forwarding preserves the caller expression's value category through a
generic wrapper using forwarding references and std::forward. Use it only in
generic forwarding code; indiscriminate forwarding obscures ownership and
overload selection.
Exercises¶
- Explain why
std::moveon aconstobject often selects copying. - Design copy and move contracts for a unique socket handle.
- Explain why moved-from does not generally mean empty.