Returning a reference to a local or temporary variable [duplicate]
Look at the code below. I know it doesn't return the address of local variable, but why does it still work and assign the variable i
in main() to '6'? How does it only return the value if the variable was removed from stack memory?
#include <iostream>
int& foo()
{
int i = 6;
std::cout << &i << std::endl; //Prints the address of i before return
return i;
}
int main()
{
int i = foo();
std::cout << i << std::endl; //Prints the value
std::cout << &i << std::endl; //Prints the address of i after return
}
You got lucky. Returning from the function doesn't immediately wipe the stack frame you just exited.
BTW, how did you confirm that you got a 6 back? The expression std::cout << &i ...
prints the address of i
, not its value.
Must be something your compiler is doing.
http://www.learncpp.com/cpp-tutorial/74a-returning-values-by-value-reference-and-address/
Confirms that your example will remove the reference from stack memory.
Returning reference or pointer to a local variable is undefined behavior. Undefined behavior means, the standard leaves the decision to the compiler. That means, undefined behavior sometimes works well, and sometimes it doesn't.
The address of i
is never going to change in main()
, but the value contained therein will. You are taking the reference of a local variable and using it after that reference has fallen out of scope. (Imprecise language warning) The value 6
is on the stack. Since you didn't do anything with the stack after you put 6
there, the reference to it will still contain the same value. So, as others have said, you got lucky.
To see just how lucky, try running this code which uses the stack after you call foo()
:
#include <iostream>
#include <ctime>
#include <numeric>
int& foo()
{
int i = 6;
std::cout << &i << " = " << i << std::endl; //Prints the address of i before return
return i;
}
long post_foo(int f)
{
srand((unsigned)time(0));
long vals[10] = {0};
size_t num_vals = sizeof(vals)/sizeof(vals[0]);
for( size_t i = 0; i < num_vals; ++i )
{
int r = (rand()%2)+1;
vals[i] = (i+f)*r;
}
long accum = std::accumulate(vals, &vals[num_vals], 0);
return accum * 2;
}
int main()
{
int &i = foo();
// std::cout << "post_foo() = " << post_foo(i) << std::endl;
std::cout << &i << " = " << i << std::endl;
}
When I ran this with the post_foo()
call commented out, 6
was still on the stack and the output was:
002CF6C8 = 6
002CF6C8 = 6
...but when I un-commented the call to post_foo()
and ran it again, 6
was long gone:
001FFD38 = 6
post_foo() = 310
001FFD38 = 258923464
While your function returns an integer by reference it is immediately assigned to the local variable 'i' in main(). That means that the stack memory allocated for foo() must persist just long enough for the return assignment. While it's bad form, this usually works. If you had tried to keep a reference
int &i = foo();
it would be much more likely to fail.