0

Recently, I was reading C++ Primer, and it said:

When a function completes, its storage is freed. After a function terminates, references to local objects refer to memory that is no longer valid

So, I type the following code in my Visual Studio 2019:

int& returnRef()
{
    int n = 2;
    return n;
}

int main()
{
    int ref = returnRef();
    cout << ref;
}

I thought it should be a case error, but it didn't and printed the correct value on command. I was confused. Is there an explanation for this?

I am new to C++.

Edit:

Thanks guys/gals. It looks like this problem is about the compiler. I got it.

BTW, I posted another question about enabling compiler warnings in vs2019: How can I enable compiler warnings in Visual Studio 2019?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Wayne JP
  • 1
  • 2
  • I believe that this is not guaranteed to work on every platform (i.e., yield the same result on every compiler), and in this case, coincidentally, the value assigned to the local variable has remained in memory after the function had completed. – goodvibration Nov 17 '19 at 09:18
  • 1
    The behaviour is undefined, no diagnostic required. However, most compilers can be configured to issue a warning on such a case - check the VS2019 documentation to see if it does. – Peter Nov 17 '19 at 09:20
  • Read [this](/questions/57842756/why-should-i-always-enable-compiler-warnings) before you write another line of C++. – n. m. could be an AI Nov 17 '19 at 09:22
  • What do you mean by _"I thought it should case error"_? Do you mean you that you expected the compiler to issue an error message or that the program will have a run-time error? – machine_1 Nov 17 '19 at 09:24

3 Answers3

3

The C++ standard does not explicitly state that such code should lead to a compiler diagnostic. However, it is featuring undefined behaviour nontheless: it may or may not work, it may change behaviour upon re-execution or on different machines or re-compilation with different versions of compilers. Most compilers will issue a warning non the less, provided you activated them upon compilation (e.g. using -Wall in GCC or /Wall in Visual Studio). GCC 10 for instance shows:

prog.cc: In function 'int& returnRef()':
prog.cc:4:12: warning: reference to local variable 'n' returned [-Wreturn-local-addr]
    4 |     return n;
      |            ^
prog.cc:3:9: note: declared here
    3 |     int n = 2;
      |         ^
Jodocus
  • 7,493
  • 1
  • 29
  • 45
2

This is undefined behavior, because the caller accesses the local variable n within returnRef() after its lifetime has ended.

The problem with undefined behavior is, that it may appear to work ok most of the time. In this case, nothing clobbers the memory occupied by n before main() reads from it. But this is not a guarantee. Even in this case, a signal that's delivered to your process at just the right time could clobber the value of n before it's copied over into ref. So, avoid this kind of UB, even if it seems to work ok and your compiler does not complain about it.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
0

"why this function can return a c++ int reference?" - It is valid syntax so the compiler will compile it, but the program has Undefined Behaviour because it breaks the rules of the language by returning a reference to a temporary. That means your program is invalid and the compiler is allowed to generate literally anything for all parts of your program and it is not required to tell you.

You can not rely on getting a compiler error every time you do something that is not allowed, you simply have to know all the rules and abide by them all, all the time.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70