1

In the following code, two functions are demonstrated. f1() returns the reference of the initialized local variable in the function scope, f2() returns the value of the initialized local variable in the function scope.

f2() is expected to work well because locally initialized variable. Value is passed from the stack to the main.

f1() is not expected to work because the reference of the local variable is useless out of the function scope. However, the output seems to ok for both functions.

Here is the test code;

#include <iostream>
using namespace std;

// function declarations
int& f1();
int f2();

int main()
{
    cout << "f1: " << f1() << endl; // should not work!
    cout << "f2: " << f2() << endl; // should work

    return 0;
}

int& f1()       // returns reference
{
    int i = 10; // local variable

    return i;   // returns reference
}

int f2()        // returns value
{
    int i = 5;  // local variable

    return i;   // returns value
}

The output is as follows;

f1: 10
f2: 5

Why f1() is working fine even that f1() returns reference of the local variable?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Levent Divilioglu
  • 11,198
  • 5
  • 59
  • 106

2 Answers2

7

Accessing a local variable out of scope is undefined behavior. Undefined behavior means the program might work, it might segfault, it might print garbage values, everything.

The low-level reason1 for that is that local variables are located on the stack. The stack belongs to the writable address space of a process (at least on most, if not all, OSes like yours). The program might write to it just like it wants to. However, writing to the stack is something what's unsupported by C++. C++ only defines local variables, not call frames or return addresses. It resides on a higher level of abstraction. The only language supporting writing directly to the stack I know of is Assembly.


1 This reason is not specified by the C++ standard by any means.

cadaniluk
  • 15,027
  • 2
  • 39
  • 67
5

Welcome to undefined behaviour!

That's what you are doing. You access a variable that has gone out of scope. However, it might be that the system hasn't written something over the value that was already there, which explains the behaviour.

That's why finding such logical errors in real code is hard. Because you might be (un)lucky and the variable has the correct value (in that particular execution).

So, f1()'s return value is a reference to something that has gone out of scope, while f2()'s return value is a copy of the local variable of that function, which is OK.


However, a descent compiler should warn you about this, with a warning of this kind:

warning: reference to local variable ‘i’ returned [-Wreturn-local-addr]

Enable your warning flags in your compiler, please. :)

gsamaras
  • 71,951
  • 46
  • 188
  • 305