c++object-lifetimetemporary-objects

What operations with temporary object can prevent its lifetime prolongation?


As you know in C++, if a temporary object is bound to a local reference, then the lifetime of the temporary is extended till the end of the scope.

But what happens if one performs a cast with a temporary or some other operation, e.g.:

#include <iostream>

struct S
{
    virtual ~S() { std::cout << "~S() "; }
};

struct U : S {};

int main() 
{
    // this temporary is destroyed in this line in GCC, and at the end in Clang
    [[maybe_unused]] auto && u = dynamic_cast<const U&>( static_cast<const S&>( U{} ) );
    std::cout << ". ";
    // this temporary is destroyed in this line in Clang, and at the end in GCC
    [[maybe_unused]] auto && s =  *&static_cast<const S&>( S{} );
    std::cout << ". ";
}

Here it is clear that both u and s reference corresponding temporary objects, still Clang and GCC prolong the lifetime of one of the temporaries only, and do not agree on which one: https://gcc.godbolt.org/z/onWKaq8MG

Are both compilers within their rights, or one of the compilers (or both) behave incorrectly?


Solution

  • I think Clang is correct.

    The lifetime of the temporary in the 1st case should be extended.

    • a const_cast, static_cast, dynamic_cast, or reinterpret_cast conversion without a user-defined conversion that converts one of these expressions to the glvalue refers to the object designated by the operand, or to its complete object or a subobject thereof (an explicit cast expression is interpreted as a sequence of these casts),

    No user-defined conversion happens here, the lifetime should be extended.

    For the 2nd case, the expression *&... is not included in the cases extending lifetime, the temporary should be destroyed after the full expression immediately.

    BTW: Gcc seems behaving differently with dynamic_cast only. Changing the dynamic_cast in the 1st case to static_cast, reinterpret_cast, or c-style conversion lifetime gets extended.