tags:

views:

163

answers:

6
#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
}

I know it doesn't return the address of local variable so that is why the warning but why does it still works and assign the variable i in main() to '6'? How does it only return the value if the variable the was removed from stack memory?

+6  A: 

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.

Marcelo Cantos
the 6 comes out when he prints it in main().
San Jacinto
@San: Well, it does now that @Dave18 edited the question.
Marcelo Cantos
Sorry, I must have read the question after this :)
San Jacinto
+1  A: 

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.

NeuroScr
+2  A: 

You aren't returning the address of i, you're returning a reference to i. There's an important difference.

In your function, when you print i, you are printing it's address since & comes before i. You told your function that it should return a reference to i, since & comes after int.

Edit: I shoud mention that other posters are of course correct... you got lucky, that's why it works.

San Jacinto
I was about to ask why this answer was down-voted. Hopefully someone reverted.
jweyrich
A: 

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.

John Gordon
+1  A: 

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.

Space_C0wb0y
And the chances of it not working well depend on the importance of the people watching the demo.
KeithB
+1  A: 

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
John Dibling