You best read this thread:
http://www.cplusplus.com/forum/beginner/222328/
Very coarsely, some expressions in the language are called rvalue-expressions, because they result in "temporary" objects. As a first approximation, an expression is an
rvalue-expression when you can't put the built-in address-of operator in front of it; conversely, an expession is an
lvalue-expression if you can.
For example, you can't take the address of the expression 42 on the right-hand side of the full-expression
|
int *p = &42 // error: 42 is an rvalue
|
Which shows that
42 is an rvalue, a temporary object.
But you can take the address of an object with a name:
1 2
|
int x;
int *p = &x; // okay: x is an lvalue
|
http://en.cppreference.com/w/cpp/language/value_category
When we attempt to initialize (or
bind) a reference to a
non-const lvalue, we must provide an lvalue expression: something we can put the
& in front of. This is because the primary purpose of a non-const lvalue reference is to modify the object it's bound to, but there's no point in modifying an object that is about to die (a temporary).
If we're intializing a
const lvalue reference, we can provide either an lvalue or rvalue expression, thanks to a special rule.
http://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary
http://en.cppreference.com/w/cpp/language/lifetime
We're taking advantage of that special rule (which exists for this purpose), so that we can add and multiply temporary matrices.
We need this because in
Matrix<4, 4> res = (identity + 2) * 3;
(identity + 2) is temporary (probably).
We could also define an overload which took an rvalue reference instead, but that would be more trouble than it is was worth:
Matrix<m, n, T> operator+(Matrix<m, n, T> && other)
About value categories & the problems they solve:
http://thbecker.net/articles/rvalue_references/section_01.html