2. Copying objects is bad
Extra memory, extra CPU cycles to copy.
May allocate heap memory, file descriptors,
etc.
May fail.
3. Temporaries
Objects not bound to a variable name
Lifetime limited to the statement that
creates them
Examples:
std::string s1, s2, s3;
std::string getName(); // prototype
std::string s4 = s1 + s2 + s3; // may copy
std::string s5 = getName(); // may copy
4. Return Value Optimization
Copy elision: optimize copies, even when
they have side effects
RVO: Elide copying of a returned temporary.
std::string getName() { return "foo"; }
std::string name = getName();
Named RVO: Elide copying of a named
variable when returned from a function.
std::string getName() {
std::string s = "foo";
return s; }
5. RVO: no guarantees
May not take effect in:
- Debug builds.
- Many but the most simple cases:
- Returning different named objects from
different return statements disables NRVO.
- NRVO does not mix with RVO.
6. Move, not copy
Do a shallow copy to the destination
Reset the source and stop using it
Useful when:
- You anyway can’t use the source later:
std::string s = s1 + s2;
// s1 + s2 is a temporary
- You know you won’t use the source later.
- Copying is expensive and can fail.
7. l-value, r-value
l-values: expressions with durable address.
May not be ok to move from.
int x = 5;foo(x);
char arr[16];arr[5] = 20;
r-values: expressions without a durable
address – temporaries – always ok to move
from.
const string& s = string("Foo"), s2, s3;
setName(getName());
s3 = s + s2;
8. Overload on l- && r-values
foo(string& s); // foo(s);
foo(const string& s); // foo(s1 + s2);
Does not work because to move from, we
need a mutable reference.
New class of mutable references – r-value
references:
foo(string& s); // foo(s);
foo(string&& s); // foo(s1 + 2);
// foo(getName())
10. Implementing move
X&& var only says it is ok to move from var.
foo(X&& var) says foo may move from var.
Implementer of foo still has to code the
actual move.
Define a nothrow swap function that
exchanges pointers and primitive types or
delegates to other swaps. Swap source with
target.
Make sure source is destructible after swap.
11. Return by value
Return by value prefers move over copy.
std::string getName() {
std::string s1;
if (s1.size() > 0) {return s1;} //move
else {return string("default");} // rvo
}
std::string s1 = getName(); // rvo or move
12. Moving l-values
You know you won’t use the source object
after this, but compiler doesn’t – so tell it.
foo(string& s); // 1
foo(string&& s); // 2
std::string s("Hello");
foo(s); // calls 1
foo(std::move(s)); // calls 2
std::move casts the l-value expression to an r-value
expression.
13. Thank you!
Q & A
Thomas Becker’s C++ Rvalue references
explained: http://bit.ly/1ACRnAe