Consider this function:
Thing func(){
return something;
}
Every call to this function, a copy of something
is made and passed
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.
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.
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.