今天早上我正在处理一些模板代码,我使用BOOST_STATIC_ASSERT
来确保我没有创建错误类型的引用,因为我认为这可能是一个更清晰的错误消息。然而,当我尝试删除静态断言以查看替代编译器错误时,我惊讶地发现当你尝试制作const double&时,gcc甚至都没有抱怨。引用一个int:
#include <iostream>
int main()
{
int x = 5;
const double& y = x;
std::cout << y << std::endl;
return 0;
}
编译,甚至不警告:
$ g++ ~/stuff/badRef.cpp -Wall -Wextra -pedantic
$ a.out
5
这里发生了什么?这是未定义的行为吗?如果是这样,为什么gcc不抱怨?在我的机器上int是4个字节而double是8.这意味着当打印double&amp;它应该将该地址的8个字节解释为double并打印出来,但该位置实际上有4个字节的int。
非常困惑。救命啊!
答案 0 :(得分:22)
const double& y = x;
创建一个值为double
的临时static_cast<double>(x)
,然后将该临时值绑定到y
。临时的生命周期延长以匹配y
的生命周期。
这是完全合法的C ++(03和11),因此缺少警告/错误。
答案 1 :(得分:11)
它定义明确且合法。 y
是指临时的。在传递参数时也要考虑:
void foo(const int& p);
foo(3.14);
另请注意,如果引用不是const ,则这不是有效的C ++ 。 VS 6得到了错误并允许将可变引用绑定到临时引用。这仅适用于const引用。
答案 2 :(得分:2)
const T&
可以绑定到临时,因此x
正在转换为double
,并且副本绑定到y
。如果您选中,则会看到&x != &y
。此行为的原因是允许将文字传递给通过const
引用获取其参数的函数。
答案 3 :(得分:1)
对于那些认为指针和引用相同的人来说,这是一个很好的例子。
double const*const y2 = &x;
gives
bad.cpp:7:30: error: cannot convert ‘int*’ to ‘const double* const’ in initialization
其他文章解释了它适用于参考文献的原因。