Part 4 - lvalue, prvalue, xvalue, glvalue, rvalue
This part is divided into 2 parts - practical part (how to use stuff) and theoritical part (complex stuff behind it). To correctly use modern C++ you DO NOT need to know the complex part. It's more for people that are curios how it works "behind the curtain".
If you have an object and you want to transfer it's ownership you can instead
Think of it as "moving" objects in memory. It's still cheaper to move than to copy tho.
What can you move? Anything that has "location in memory". For example
std::move(4) doesn't really make sense. In that case you can think about
std::move as converting a variable into "something" like
After moving, object "moved from" is left in "valid, but unspecified state" which means - don't touch it.
auto a = 5; // after doing std::move we cannot touch a // type of b is "int&&" auto b = std::move(a); // not using auto on purpose that you can assign it to a variable // since it "became something like 4" int c = b;
This part will be really boring, but it's a pathway to many abilities some consider to be unnatural.
If you're brave, you can read the [basic.lval]. This part will oversimplyfy things by a lot. The goal isn't to teach C++ standard - the goal is to understand how to use it. I don't know which explanation will be the most intuitive for the reader, so I'm just putting in all of them.
|type||has identity||can be moved from|
|glvalue||xvalue or lvalue|
|rvalue||xvalue or prvalue|
gvalue - they really denote to locations (in memory). When you have a variable - it is stored somewhere in memory (go back to part1 if this is confusing).
int a(every variable has a location)
prvalue - used for initialization of an object
4(yes, just a simple number)
- xvalue - glvalues that denote objects that are at the end of their lifetime or are otherwise marked for being able to have their resources reused
- lvalue - gvalue that is not xvalue
- rvalue - prvalue taht is not xvalue
// all assignments - lvalue a = b; // name of variable, function or data member - lvalue std::cin // literal - rvalue 42 // stuff like this - rvalue str1 + str2 // rvalue reference to an object - xvalue a = std::move(x);
std::moveproduces xvalue that identifies it's argument. It's effectively a
static_castto rvalue reference.
std::forwardpasses it's argument along with same value type as it had before. At first you might think it's useless, but when you call a function with the value
4as an argument, it clearly was a prvalue, but now it became a variable that you can use inside the function, thus having identity and becoming a glvalue.
std::forwardavoids that, which will be usefull in part5.