简体   繁体   中英

Why should I ever return something by value, since C++ features const references?

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, eg:

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? Eg "default to returning by value" ? Or is it purely based on the specific case?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM