This is my learning notes from the course - Mastering C++ Standard Library Features.
Lvalues and Rvalues
Why to talk about Lvalues and Rvalues in C++?
Knowledge of value categories and references is necessary to understand move semantics
and ownership transfer.
Move Semantics - Sneak Peek
- Move semantics revolve around the idea of transferring ownership of resources instead of copying them.
- They increase performance, safety, and readability of libraries and applications.
1 | // C++03 |
As an example, in C++03, if you have a vector v0
containing some data and another vector v1
, and you want to move all the data into v1
, you had no way of expressing the idea of transferring the resource from v0
to v1
, so you were forced to make a copy. In C++11 and later, we have this new library function called std::move
that allows you to express the intent of moving the contents of v0
into v1
, resulting in safer and more efficient code. Understanding value categories and Lvalues and Rvalues is the Key to understanding how std::move
works and what move semantics are.
Value Categories
Lvalues
- Can appear on the left side of built-in assignment operator
- Can take its address
- Can bind to lvalue references
1 | int& bar() { static int i = 0; return i; } |
Rvalues
1 | int bar() { return 5; } |
References
1 |
|
Summary
- C++ expressions have a value categories; they can either be Lvalues or Rvalues
- Lvalues can appear on the left side of built-in assignment, Rvalues cannot
- Non-const Lvalue references can only bind to Lvalues
- Non-const Rvalue references can only bind to Rvalues
Move Semantics
Meaning of Rvalues
An rvalue represents a temporary object that has no identity. We can assume that an rvalue is ready to give away ownership of its resources.
1 |
|
What are Move Semantics?
- Transferring ownership of resources instead of copying them
- Relying on Rvalue references
- Colloquially express the idea of “moving” objects
std::move
- It’s literally a cast to an Rvalue reference
- Doesn’t actually “move” anything, but expresses “intent to move”
- Can be used to turn an Lvalue into an Rvalue
- It is generally unsafe to use an object after it has been moved
- Moving when returning is unnecessary and sometimes detrimental
1 |
|
At line 16, the interesting part of this operation, the transferring of the ownership of the resource inside the vector happens in the vector’s move constructor implementation. std::move
doesn’t have to do anything fancy. It is, again, just a cast, meaning that std::move
doesn’t actually move anything.
One important thing is that using a value after it has been moved can lead to undefined behavior. That’s because implementation of the move constructor or move assignment, or any other move operation, assumes that the object is about to expire and it may leave the object in a valid, but unspecified state.
Summary
- Learned that the Rvalue expressions represent temporariness and lack of “identity”
- Learned that the
std::move
is just a cast to an Rvalue that expresses the “intention” of moving - Understood that it is unsafe to use objects after they have been “moved from”
- Learned that moving when returning is unnecessary and sometimes detrimental