19

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?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Aviv Cohn
  • 15,543
  • 25
  • 68
  • 131
  • 13
    In this example, your "optimization" results in an extra copy being made in `Thing thing = func();` because you kill return value optimization. You also kill move semantics. On top of that, the caller cannot know that the object they refer to will not get mutated at some point. Referential semantics are hard to reason out. – juanchopanza Oct 06 '14 at 17:22
  • 1
    Ownership, RVO, move semantics, charity. – Captain Obvlious Oct 06 '14 at 17:23
  • @juahcnopanza if `something` was itself a reference, then the optimization is good – M.M Oct 06 '14 at 22:37
  • Related question: [Is returning by rvalue reference more efficient?](http://stackoverflow.com/q/1116641/315052). – jxh Oct 07 '14 at 03:59
  • 1
    @MattMcNabb: If `something` was itself a reference, this would not be an optimization. This would be semantic common sense, since it's not a value you're returning. – Laurent LA RIZZA Oct 07 '14 at 05:53
  • 1
    Because values are a lot easier to reason about than references. A value just is, you don't have to manage its life cycle, own it, disown it, worry about what happens when you throw, clean up after it and so on. A value just is - it's super easy to use and super easy to reason about. – Benjamin Gruenbaum Oct 07 '14 at 07:06

3 Answers3

25

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.

Marco A.
  • 43,032
  • 26
  • 132
  • 246
  • The second half of the question's title says "**when I can** return it by const reference". – barak manos Oct 06 '14 at 17:28
  • Checking that I understand the first paragraph: *"...if your object (for whatever reason) was created on the stack of the called function, returning a reference to it is undefined behavior."* - Is that because when the function returns, anything local to that function is deleted, and the const reference ends up referring to nothing? – Aviv Cohn Oct 06 '14 at 17:28
  • 6
    @AvivCohn accessing memory through a reference of a stack object no longer in scope is undefined behavior, an invalid operation which cannot be trusted on the result – Marco A. Oct 06 '14 at 17:30
  • So does it *ever* make sense to return a reference (const or not) to a function-local variable? – Aviv Cohn Oct 06 '14 at 17:33
  • @AvivCohn Except some special cases when you have some guarantees on the stack frame (and I don't think that is standard behavior), I believe it doesn't. In any case you shouldn't. If someone feels like this is wrong please let me know. – Marco A. Oct 06 '14 at 17:36
  • 4
    @AvivCohn: It could make sense if it's static. If it's automatic, then returning a reference to it is always an error. – Mike Seymour Oct 06 '14 at 17:36
  • @MikeSeymour If I'm not mistaken, the compiler doesn't issue an error if you return a reference to a function-local variable. Any reason for that? – Aviv Cohn Oct 06 '14 at 17:38
  • Marco: is there any 'default' I should go with? Should I usually just return by value? Or by const reference? Or is it purely based on the specific case? – Aviv Cohn Oct 06 '14 at 17:40
  • 1
    @AvivCohn: I'm not sure why a diagnosis isn't required; perhaps because it's impossible to diagnose in general (e.g. if you return a reference returned by another function, like `return std::max(local1, local2)`. But most compilers will give a warning, as long as you enable it. – Mike Seymour Oct 06 '14 at 17:43
  • 2
    @AvivCohn I would consider each case separately, also depending on the semantics of your code. And anyway: `-Wreturn-stack-address`, AFAIK the standard doesn't mandate to issue a warning. It's always good when someone does, though. – Marco A. Oct 06 '14 at 17:44
  • "returning a reference to it" isn't immediately invoking UB. – Columbo Oct 06 '14 at 19:09
  • @Loopunroller rephrased – Marco A. Oct 06 '14 at 19:30
  • 1
    @AvivCohn Variables with automatic storage duration are not deleted, that only applies to dynamically-allocated storage, but their destructors will be called when an automatic variable of a class type goes out of scope, meaning it will no longer be in a valid state. For PODs often a reference to an automatic variable will still work after the variable it refers to has gone out of scope, until it gets clobbered by the next function call, but you should never count on it, especially since in C++, functions are often called implicitly. – bcrist Oct 06 '14 at 21:53
  • 1
    From your comments on various answers, it seems that you are keen on getting an one-fit-all answer. Unfortunately, C++ is not designed to be easy. You have to understand deeply how reference, pointers and object lifetime works and there is no simple rule you can just remember to deal with them. – Siyuan Ren Oct 07 '14 at 10:52
8

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.

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • 1
    Thanks for your answer. Apart from the case of returning a local variable - in which case as you say I should always return by value - is there a default I can go with? E.g. always return by const ref? What should I do in general when the case isn't exceptional? – Aviv Cohn Oct 06 '14 at 17:43
  • 1
    @AvivCohn See the edit. The default is to return by value, but you have to know the difference. – Columbo Oct 06 '14 at 17:45
6

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.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Thanks for answering. Apart from returning a local variable (in which case as you say I must return by value), is there any default I should go with? E.g. should I always just return by const ref if the case isn't exceptional? Or by const ref? What should I do in general? – Aviv Cohn Oct 06 '14 at 17:42
  • @AvivCohn: I'd return simple types by value for simplicity; and use my brain for complicated types. As I said in the answer, "it's generally better to return a reference and let the caller decide whether it should be copied" - but there are situations when you wouldn't. – Mike Seymour Oct 06 '14 at 17:48