我刚刚在 Going Native 2012 上观看了 Chandler 关于 Clang 的演示。他提供了以下代码:
#include <iostream>
struct S{ int n; };
struct X{ X(int) {}; };
void f( void* )
{
std::cerr << "Pointer!\n";
}
void f( X )
{
std::cerr << "X!\n";
}
int main()
{
f(S().n);
}
钱德勒表示这称为f(void*)
对于 c++11 和f(X)
对于c++03。
他还指出原因是 S().n 默认初始化为 0,使其成为nullptr
持续的。
首先,我是否正确地假设成员变量 n 的零初始化取决于编译器实现,并且不受标准保证(或者这在 c++11 中发生了变化)?钱德勒暗示这是由于对常量表达式的支持,但我仍然不能完全理解他的推理。
其次为什么会f(X)
用 C++03 而不是 c++11 调用?我会假设f(void*)
无论价值如何都会启动S().n
通过隐式转换为X
有关 Chandler 的解释,请参阅以下链接,45 分钟:
Clang:从 Murphy 的百万猴子中捍卫 C++
首先,我假设成员的零初始化是正确的
变量 n 取决于编译器实现,并且不能保证
标准(或者 c++11 改变了这一点)?
No, S()
在 C++03 和 C++11 中都表示值初始化。尽管我相信 C++11 中的措辞比 C++03 中的措辞要清晰得多。在这种情况下,值初始化转向零初始化。将此与不为零的默认初始化进行对比:
S s1; // default initialization
std::cout << s1.n << '\n'; // prints garbage, crank up optimizer to show
S s2 = S(); // value initialization
std::cout << s2.n << '\n'; // prints 0
其次,为什么 f(X) 会用 C++03 而不是 c++11 来调用?我会的
假设无论 S().n 的值如何,f(void*) 都会启动
通过隐式转换到 X
在 C++03 中int
永远不能成为空指针常量。一次0
被键入为int
,比如将其分配给int
,那么它就永远是一个int
,而不是空指针常量。
在 C++11 中,S().n
隐式地是一个constexpr
具有价值的表达0
, and a constexpr
具有价值的表达0
可以是空指针常量。
最后,据我所知,这并不是委员会有意的改变。如果您正在编写依赖于这种差异的代码,那么将来如果/当委员会自行纠正时,您很可能会受到影响。我会避开这个区域。用它来赢得酒吧赌注——而不是在生产代码中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)