c++compiler-optimizationstdtuplestructured-bindings

Why does optimizing with std::forward_as_tuple produce runtime errors?


Let's consider the following program:

#include <iostream>
#include <tuple>
using namespace std;

const int* f()
{
    static int i = 5;
    return &i;
}

int main()
{
    auto [a] = std::forward_as_tuple( f() );
    //auto&& [a] = std::forward_as_tuple( f() );           // same error
    //const auto& [a] = std::forward_as_tuple( f() );      // same error
    cout << *a << endl;
    return 0;
}

I expect it to print 5. I tried it on gcc 13.1 and MSVC 19.35, and it produces correct result when all optimizations are turned off. Anyway, when I add -O1 for gcc or /O2 for MSVC, the program starts crashing in runtime, and I can hardly understand why this happens. I found the following Note on cppreference:

If the arguments are temporaries, forward_as_tuple does not extend their lifetime; they have to be used before the end of the full expression.

Is it the explanation? If so, can someone please elaborate what language rules am I violating in my code?


Solution

  • Following the trail that @NathanOliver had laid I managed to find an answer at cppreference:

    a temporary bound to a reference parameter in a function call exists until the end of the full expression containing that function call: if the function returns a reference, which outlives the full expression, it becomes a dangling reference.

    and

    In general, the lifetime of a temporary cannot be further extended by "passing it on": a second reference, initialized from the reference variable or data member to which the temporary was bound, does not affect its lifetime.