Jaebum
Jaebum

Reputation: 1570

Returning the local reference versus local variable of the reference-returning-function

I know that for the functions that returns the reference, it is an undefined-behavior to return the reference of the local variable. For example,

int& test(int a) {
    return a;
}

Compiler will emit

<source>: In function 'int& test(int)':

<source>:4:9: warning: reference to local variable 'a' returned [-Wreturn-local-addr]

    4 |  return a;

      |         ^

<source>:3:15: note: declared here

    3 | int& test(int a) {

      |           ~~~~^

But surprisingly, if I define the reference inside of the function and returns it, compiler does not complain anymore.

int& test(int a) {
    int& b = a;
    return b;
}

Why is this the valid case? Doesn't b references the local variable anyway?

Upvotes: 0

Views: 104

Answers (2)

Jerry Coffin
Jerry Coffin

Reputation: 490098

But surprisingly, if I define the reference inside of the function and returns it, compiler does not complain anymore.

I guess the big question here is: what compiler?

Doing a quick test with g++ (9.2), I get:

trash9.cpp: In function 'int& test(int)':
trash9.cpp:3:12: warning: function returns address of local variable [-Wreturn-local-addr]
    3 |     return b;
      |            ^
trash9.cpp:1:15: note: declared here
    1 | int& test(int a) {
      |           ~~~~^

With VC++ (19.28), things are a tiny bit more complex. If I compile that function in isolation, I don't get a warning, but if I compile it along with some code that calls it, then I do get a warning:

C:\C\source\trash9.cpp(3) : warning C4172: returning address of local variable or temporary: a

With clang++ (10.0), I get:

trash9.cpp:3:12: warning: reference to stack memory associated with parameter 'a' returned [-Wreturn-stack-address]
    return b;
           ^
trash9.cpp:2:10: note: binding reference variable 'b' here
    int& b = a;
         ^   ~

So I guess if I had to answer the question directly: no, it's not valid, and yes, compilers can and do warn about it.

Some people are probably bored of hearing me say it, but I'll say it again anyway: it's worth keeping at least a couple of compilers handy--sometimes one will warn about something that another doesn't, and the warning can tell you about a problem that might be much more difficult to find and fix on your own.

Upvotes: 3

tadman
tadman

Reputation: 211560

Just because you fake out the checker doesn't mean this code is suddenly well-behaved, it's not.

Returning a reference to a temporary local variable is undefined behaviour. The compiler catches trivial cases, but it doesn't catch every case.

The trouble with undefined behaviour is you can have it without even realizing. No warnings. No errors. No indication at all apart from your program behaving badly.

Upvotes: 3

Related Questions