First, just for clarification, there is a third reason for the parameter to be made const. Non const parameters cannot be used for const arguments. So we again needlessly restrict the use of the function. As a rule of thumb, the keyword const should be used proactively all over our code.
But to answer your question, I'm sure others will be able to give you a better explanation. But this is my try:
> operator -, returns by value as we all know, but, after the return statement, a unnamed temporary is created W/the value of the return statment and this results in an rvalue.
Correct.
> I don't see how a non-const argument, would not work - problem/error free - in the OP's code because a temporary is still a valid object in that it *is* useable as an rvalue and lvalue *until* the end of the semicolon of the statement where vector::cross is called.
No. an rvalue cannot be both an rvalue and an lvalue. Technically neither an lvalue can. But what distinguishes them is that lvalues can be used either on the right or left hand-side of an assignment, while an rvalue cannot. It can only be used on the right-hand side.
What happens when vector::cross is called?
First, there's all the name matching thing going on. We can skip that. We are interested on the building of that 2nd parameter....
That second argument (
p - body.x) is evaluated. A matching operator overload is found and the code within is ran. It then returns a Vector object as an rvalue. Just an rvalue. It can't be used as the left-hand side of an assignment. You are about to know why I'm giving so much importance to this.
The function declaration defined the second parameter as a plain reference to Vector. As you know references refer directly to the objects they "point" to. They are simply just another name for that object. But what object is this? Certainly not the return value from the operator overload. If it was, it had to be an lvalue.
Why? Well look closely at the following 3 lines:
Code:
int foo = 12;
int &bar = foo;
bar = 23;
bar is a reference to foo. When I change bar's value I am actually changing foo's value, as you well know. But for foo value to be changed, it has to be on the left-hand side of an assignment. So, foo has to be a lvalue.
Since the return statement from the subtraction is an rvalue, it cannot be directly made a reference of. Because it assumes the value of the reference can be changed. But it can only change if the object it refers too is an lvalue as you saw from the code above.
Const references (or references to const. More correct) change all that. Since the value cannot be changed, it is safe to build the reference from an rvalue. What will happen is that a temporary will first be created. This temporary will be assigned the value of the operator overload. Then the Vector reference parameter will be created and assigned with the temporary.
> The reason, as I have come to know, why temporary rvalue objects should be treated as an rvalue only and marked as const, is because they only exist for a short period and once the end of the statement (or sequence point) is reached where the temporary object was created, then, the object will be destroyed. So I don't see the OP's code, without the constness argument, problematic.
I hope the above clarified it. The temporary exists after the return object has been created. This will be a real-live local object. The temporary is created from it and the parameter will be created from the temporary.