Why does this C++ snippet assigning a value to an rvalue compile?
a*b = c;
calls the assignment operator on the Rational
returned by a * b
. The assignment operator generated is the same as if the following were defined:
Rational& Rational::operator=(const Rational&) = default;
There is no reason why this shouldn't be callable on a temporary Rational
. You can also do:
Rational{1,2} = c;
If you wanted to force the assignment operator to be callable only on lvalues, you could declare it like this, with a &
qualifier at the end:
Rational& operator=(const Rational&) &;
"a*b is an r-value, and hence have no location in memory" it is not quite right.
I add prints. The comments are the prints for each line of code
#include <iostream>
using namespace std;
struct Rational {
Rational(int numer, int denom) : numer(numer), denom(denom) {
cout << "object init with parameters\n";
}
Rational(const Rational& r)
{
this->denom = r.denom;
this->numer = r.numer;
cout << "object init with Rational\n";
}
~Rational() {
cout << "object destroy\n";
}
int numer, denom;
};
Rational operator*(const Rational& lhs, const Rational& rhs) {
cout << "operator*\n";
return Rational(lhs.numer * rhs.numer, lhs.denom * rhs.denom);
}
int main() {
Rational a(1, 2), b(3, 4), c(5, 6); // 3x object init with parameters
cout << "after a, b, c\n"; // after a, b, c
Rational d = a * b = c; // operator*, object init with parameters, object init with Rational, object destroy
cout << "end\n"; // end
// 4x object destroy
}
In the line Rational d = a * b = c;
d
is equal to c
. This line call operator*
function, that call the object init with parameters constructor. After that c
object is copied to d
object by calling copy constructor.
If you write the line: Rational d = a = c; // d == c // print only: object init with Rational
the compiler assign the d
object only to the last assign (object c
)