1

Consider the following program:

class C { ... }; const C f() { C ret; cout << &ret << endl; return ret; } int main() { C value = f(); cout << &value << endl; } result: // note the address are the same 0x7ffdd24b26e0 0x7ffdd24b26e0 

The variable 'ret' in function f() and variable 'value' has the same memory address so it seems 'value' is not a copy of 'ret'. The variable 'ret' is a stack variable so it should be invalidated after f() returns. So why c++ allow returning a stack value inside a function?

g++ version:

g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 
1
  • There's no need to add a note about your second question being moved on either the first post or the second post. That's just extra noise. Commented Jul 5, 2016 at 21:39

4 Answers 4

4

The reason for the address of ret and value being the same is the so called Return Value Optimization (RVO). It means that in this case a copy is not going to be performed. Note however, that you can not rely on this, as it is not bound to happen (although that will change with C++17 [at least the current draft]).

https://en.wikipedia.org/wiki/Return_value_optimization

Sign up to request clarification or add additional context in comments.

2 Comments

RVO explains it very well. Thanks.
Might be nitpicking, but this is actually a case of NRVO (Named Return Value Optimization).
3

This is an example of copy-elision, specifically RVO (return value optimization). It allows you to avoid the performance penalty of returning an object.

I've worked with a lot of people who were unaware of RVO and wrote stuff like:

void get_stuff(std::vector<int>& foo /*and input params*/) { // add a whole lot of integers into foo. } 

because they thought this would be cheaper (by avoiding a copy) than:

void get_stuff(/*input params*/){ std::vector foo; // populate foo. return foo; } 

This leads to unnecessarily verbose, and often difficult to read code. It's quintessential premature optimization -- a mistake you won't be making, since you now know about RVO!

1 Comment

And knowing is half the battle. Yo JOE!
1

Returning the function result by value is one of the places, where the compiler is allowed to elide a copy as an optimization and thus translates your code to the moral equivalent of this :

void f(uint8_t* memory) { new(memory) C; // create object reserved memory location cout << (size_t)memory << endl; } int main() { alignas(alignof(C)) uint8_t value[sizeof(C)]; //<- reserve properly aligned raw storage of appropriate size on the stack f(value); cout << (size_t)&value[0] << endl; } 

This optimization technique is called NRVO (named return value optimization) and is actually a pretty natural consequence of most calling conventions which specify that - for values that can't be returned via a register - the returned value is put at an address that is specified by the caller anyway.

Comments

0

I'm not sure whether this is actually RVO. An equally valid hypothesis is that the storage of both ret and value is on the implementation's stack, and that they share the same stack slot because their lifetimes are effectively non-overlapping. There might have been an intermediary.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.