问题描述
如您所知,在 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 << ". ";
}
这里很明显 u
和 s
都引用了对应的临时对象,但 Clang 和 GCC 仍然只是延长了其中一个临时对象的生命周期,并没有就哪一个达成一致:{{3 }}
两个编译器是否都在其权限范围内,或者其中一个(或两者)的行为不正确?
解决方法
我认为 Clang 是正确的。
第一种情况下的 lifetime of the temporary 应该扩展。
- 没有用户定义的转换的 const_cast、static_cast、dynamic_cast 或 reinterpret_cast 转换将这些表达式之一转换为泛左值指的是操作数指定的对象,或其完整对象或其子对象(显式强制转换表达式被解释为这些强制转换的序列),
这里没有发生用户定义的转换,应该延长生命周期。
对于第二种情况,表达式 *&...
不包括在延长生命周期的情况中,临时应在完整表达式之后立即销毁。
顺便说一句:Gcc 似乎只有 dynamic_cast
的行为不同。将第一种情况下的 dynamic_cast
更改为 static_cast
、reinterpret_cast
或 c 样式转换生命周期会得到延长。