NOTE: Explaining rvalue-ref within few lines of comment cannot suffice, I advise you read more about it or perhaps learn from the experts.
MemoryBlock {} or MemoryBlock() creates a temporary object whose lifetime doesn't exceed where they're used. Rvalue, loosely speaking, appears on the rhs of an expression OR are basically objects with a short lifespan such as when you create temporaries(object created on the fly or the result of a function call) or a moved-from object(usually via std::move()). Rvalue references is a C++11 "feature" that allows temporary objects to be bind, such that their lifespan can be "prolonged." Thus, the name - rvalue reference( reference to an rvalue object ).
Your question is quite simple, so I'm gonna rephrase: How does the compiler choose an overloaded function for rvalue-ref and lvalues?
Since we know that when you create a temporary, or a moved-from object, they can be bound to an rvalue-reference. The compiler checks the type of the object in the argument list(s) and says "is this a temporary object or an lvalue?" For the latter it choose a cv-qualified ref, otherwise if the former is the case, it choose an rvalue ref. See the below example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
//necessary headers, and I assume print() outputs to the output stream
struct T;
void f( T && a ){
print(rvalue);
}
void f( const T & a) {
print(lvalue);
}
T T_factory() {
return T {};
}
int main(){
T t_object;
f( t_object ); //calls f( const T &), t_object is an lvalue
f( T_factory() ); //calls f( T && )
f( std::move(t_object) ); //calls f(T && )
//note that t_object is in an unsafe state, careful!
}
|
If function f() wasn't overloaded with an rvalue-ref of that same object, all calls to f() would choose the cv-qualified version of f().