有这个代码:
#include <iostream>
void test(const int& val)
{
const_cast<int&>(val) = 42;
}
int main()
{
int val1 = 0, val2 = 0, val3 = 0;
test(val1);
test(val2 + 0);
test(static_cast<int>(val3)); //Интересная строка;
std::cout << val1 << " " << val2 << " " << val3 << std::endl;
return 0;
}
42 0 0
42 0 42
谁是对的,为什么?
static_cast<int>(val3),根据[expr.static.cast]p1,是一个右值表达式。根据[dcl.init.ref]p5.3,使用右值表达式初始化 const 引用会具体化 prvalue,创建一个 const临时对象并将引用绑定到它。
[dcl.type.cv]p4明确禁止我们修改 const 对象。
基于所有这些观点,正确的答案将是
42 0 0,但是因为。在第二种和第三种情况下,我们有未定义的行为,那么输出可以是任何东西。因此,一般来说,谈论正确答案是没有意义的。但是,studio 输出
42 0 42不是因为 UB,而是因为没有 flag/permissive-,它的扩展被触发,static_cast当类型没有改变时忽略。结果,在第三种情况下,传递的是左值,而不是右值。但是这种行为违反了标准,并且是 MSVC 的扩展,我相信它的存在是为了实现一些向后兼容性。