Cpp - Notes on more modern concepts
Different types of values
Upon the introduction of move semantics, meaning expressions that can be moved and not copied, new types of values needed to be defined. These new value types were in addition to the old l and r values.
- lvalue - designates a function or object. Historically called so because lvalues could appear on the left-hand side of an assignment.
- xvalue - designates an “eXpiring” value, usually near the end of its lifetime such that its resources may be moved. An xvalue is the result of certain kinds of expressions involving rvalue references. Example, the result of calling a function whose return type is an rvalue reference; this is an xvalue, such as when using std::move.
- glvalue - (“generalised” lvalue) designates an lvalue or an xvalue
- rvalue - is an xvalue, a temporary object or a value that is not associated with any object. Historically called so because rvalues could appear on the right-hand side of an assignment.
- prvalue - (“pure” rvalue) is an rvalue that is not an xvalue.
Rule of Three/Five/Zero
Taken from: https://en.cppreference.com/w/cpp/language/rule_of_three
Rule of Three
If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.
Rule of Five
If a destructor, copy-constructor or copy-assignment is user defined this prevent implicit definition of the move constructor and move assignment operator. Any class for which move semantics are desirable has to declare all five special member functions.
Unlike the Rule of Three, failing to provide mode constructor and move assignment is usually not an error, but a missed optimisation opportunity.
There is a generic wording for this principle: If you define or =delete any default operation, define of =delete them all
Rule of Zero
Classes that have custom destructors, copy/move constructors or copy/move assignment operators should deal exclusively with ownership.
Taken from: https://youtu.be/7Qgd9B1KuMQ?t=1394
If your class does not directly manage any resource, but merely uses library components such as vector and string, then you should strive to write no special member functions. default them all.
- Let the compiler implicitly generate a defaulted destructor
- Let the compiler generate the copy constructor
- Let the compiler generate the assignment operator
- However, implementing swap might improve performence
There are two kinds of well-designed value-semantic C++ classes:
- Business-logic classes that do not manually manage any resources, and follow the Rule of Zero.
- Resource-management classes They delegate the job of resource management to data members of types such as std::string.
- Resource-management classes (small, single purpose) that follow the Rule of Three. Acquire the resource in each constructor. Free the resource in the destructor. Copy-and-swap in the assignment operator.