Both f2
and f3
have undefined behaviour. You are returning references to local variables. Those local variables are destroyed when the function ends, and the reference is dangling.
The difference between a const reference, and a non-const reference is that a const reference can bind to both rvalues and lvalues.
For non-const references you have to distinguish between lvalue-reference(int&
) and rvalue-reference(int&&
).
So using the function signature int&& f2(int a)
would also compile, but equally have undefined behaviour.
The main reason this is usefull is because when we pass a reference to a function, the function signature tell us if we are expecting an lvalue or an rvalue. We can also overload both and decide to move/copy depending on what we get.
In the case where we don't care, or if we only want to read from the value we can use a const reference and be able to accept both lvalues and rvalues that are passed in.
void foo(MyClass& mc) {
// We know mc is an lvalue.
// We could copy mc, or modify it if we want to use it as an output parameter.
}
void foo(MyClass&& mc) {
// We know mc is an rvalue.
// We know it would be safe to move from mc in this case.
}
MyClass mc;
foo(mc); // Callsthe first overload
foo(MyClass{}); // Calls the second overload
// The two functions above can be overloaded, so we can make sure we deal
// with both cases in the right way
void foo2(const MyClass& mc) {
// This can be both an rvalue or lvalue.
// We don't really care since the reference
// is const we are only going to read from it.
}
foo2(mc); // Both calls work
foo2(MyClass{});
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…