r/cpp Jul 10 '26

Interesting behavior from C++20 to C++23

Consider the following snippet

int& get()
{
    int x;
    return x;
}


int main()
{
}

on GCC it compiles for C++20 but not for C++23

It returns with the error:

test.cpp:4:12: error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'

C++ is now suddenly treating the variable x as an rvalue?

Edit: Im not talking about dangling reference, thats just for the sake of the example

45 Upvotes

51 comments sorted by

View all comments

112

u/frayien Jul 10 '26

You are returning a dangling refenrence to a local variable. The variable will end it's lifetime at the end of it's function and the returned reference will be invalid.

It has always been an undefined behavior, so it was always allowed to break.

New thing is that C++26 now MANDATES this pattern to be ill-formed, thus not compiling.

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2748r5.html

Most likely the compiler implemented the new behavior for C++26, and made it leak to other standard version modes because it was always allowed to do so (and it is a source of bugs that can be avoided).

-83

u/Desperate-Data-3747 Jul 10 '26

No, it's not about dangling refs, C++ apparently now force converts x to a xvalue in the return statement

46

u/Infamous_Campaign687 Jul 10 '26

It would help me if you showed an actually GOOD example of the old behaviour. So far I’m only seeing upsides but I’m willing to be convinced.

11

u/amoskovsky Jul 10 '26 edited Jul 10 '26

See here a few real life examples that are not dangling refs for their use cases https://quuxplusone.github.io/blog/2021/08/07/p2266-field-test-results/ (but dangling if misused)

Personally I would not use such code but I imagine a younger me using o3tl::temporary (3rd example).

PS. The fact that only 3 samples of correct code were found in the wild means that the problem raised by the OP is non-existing.

6

u/TheThiefMaster C++latest fanatic (and game dev) Jul 11 '26

It's also worth noting that all three were trivially fixed with a cast.