Consider this function:
Thing func(){
return something;
}
Every call to this function, a copy of something
is made and passed to the caller.
My question is, why not just do this (every time I want to return something by value)?
const Thing& func(){
return something;
}
This way, we're not risking copying something
without a reason to do so. If the client only needs to 'read' from something
, but not 'write' to it, a const reference can do exactly that. And if the client does need a copy, it can simply assign the const reference to a variable, e.g.:
Thing thing = func(); // the object is passed by const reference, and then copied.
So is there ever a reason to simply return by value?
By the way, it's not that I care so much about optimization, it's just that I don't see a reason to ever return simply by value.
Follow up question: reading the answers, I understand that there are pros and cons for each method. Is there a default? E.g. "default to returning by value"? Or is it purely based on the specific case?
Returning a reference returns by reference. In addition to allowing modification of the returned object, this does not make a copy and saves whatever effort would have been consumed by making a copy.
From what I understand: when you pass by value, the function makes a local copy of the passed argument and uses that; when the function ends, it goes out of scope. When you pass by const reference, the function uses a reference to the passed argument that can't be modified.
C does not support references or passing by reference. You should use pointers instead and pass by address. Pass-by-value is efficient for primitive types, but does a shallow copy for structs. In C++ it makes a LOT of sense to pass objects by reference for efficiency.
A const reference is actually a reference to const. A reference is inherently const, so when we say const reference, it is not a reference that can not be changed, rather it's a reference to const. Once a reference is bound to refer to an object, it can not be bound to refer to another object.
Because if your object (for whatever reason) was created on the stack of the called function, returning and using a reference to it is undefined behavior.
With return-by-value the compiler can sometimes optimize the return and there are no dangerous dangling references. With C++11 and move semantics this is brought to a new level.
It doesn't quite make sense to say "it's always better to return by reference rather than by value", each case where one is used, must be considered separately.
So is there ever a reason to simply return by value?
Yes. If you are returning a function local variable, for instance.
int compute(int a, int b)
{
int result;
// a lot of magic
return result;
}
If that function was to return a reference to result
of any kind, it would be a dangling one.
Apart from that, returning function local variables with class type "by value" can be optimized with copy elision - the name of the optimization is NRVO. And if that optimization doesn't apply, the newly introduced move semantics might (although you should just rely on copy elision, it works pretty well). There is just no incentive to return a reference in such cases.
Moreover, you wouldn't want to return references if you wish to keep things private. Why would you return a const reference to a private member variable in a public member function? It indicates that the member variable exists, information that the call site doesn't have to know.
Also consider thread safety: Returning variables by reference might lead to a data race if the same object is being modified by another thread after the return
-statement.
Or is it purely based on the specific case?
Most of the time you will return by value, especially for non-member functions. Member functions might return references to members*, but there are hardly scenarios where a non-member function returns references. You should only return references when you know that you need to (and what you're doing).
* And also only if they really need to.
If you're returning a non-static local variable, then you must return by value, since it will be destroyed when the function returns, making any references to it invalid. In that case, the copy can often be replaced by a move, or elided altogether.
If you're returning something persistent, then you're right; it's generally better to return a reference and let the caller decide whether it should be copied. But there might be other reasons such as thread safety to prefer returning by value even then: by returning a copy, the reader can't access the persistent object while another thread might be modifying it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With