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