对临时对象的哪些操作可以防止其寿命延长?

问题描述

如您所知,在 C++ 中,如果临时对象绑定到本地引用,则临时对象的生命周期会延长到作用域结束。

但是如果使用临时或其他一些操作执行强制转换会发生什么,例如:

#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 << ". ";
}

这里很明显 us 都引用了对应的临时对象,但 Clang 和 GCC 仍然只是延长了其中一个临时对象的生命周期,并没有就哪一个达成一致:{{3 }}

两个编译器是否都在其权限范围内,或者其中一个(或两者)的行为不正确?

解决方法

我认为 Clang 是正确的。

第一种情况下的 lifetime of the temporary 应该扩展。

  • 没有用户定义的转换的 const_cast、static_cast、dynamic_cast 或 reinterpret_cast 转换将这些表达式之一转换为泛左值指的是操作数指定的对象,或其完整对象或其子对象(显式强制转换表达式被解释为这些强制转换的序列),

这里没有发生用户定义的转换,应该延长生命周期。

对于第二种情况,表达式 *&... 不包括在延长生命周期的情况中,临时应在完整表达式之后立即销毁。

顺便说一句:Gcc 似乎只有 dynamic_cast 的行为不同。将第一种情况下的 dynamic_cast 更改为 static_castreinterpret_cast 或 c 样式转换生命周期会得到延长。