C++11 中的默认构造函数、POD 初始化和隐式类型转换

2023-12-08

我刚刚在 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(使用前将#替换为@)

C++11 中的默认构造函数、POD 初始化和隐式类型转换 的相关文章

随机推荐