繁体   English   中英

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

[英]Default constructors, initialization of POD and implicit type conversions in C++11

我刚看了Chandler在2012年Going Native上对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);
}

Chandler声称这对c ++ 11调用f(void*)而对c ++ 03调用f(void*) f(X) 他还指出原因是S()。n默认初始化为0,使其成为nullptr常量。

首先,我正确地假设成员变量n的零初始化是依赖于编译器实现的并且不是由标准保证(或者用c ++ 11进行了这种改变)? 钱德勒暗示这是由于对持续表达的支持,但我仍然不能完全遵循他的推理。

其次,为什么用C ++ 03而不是c ++ 11调用f(X) 我假设f(void*)无论S().n的值是否隐式转换为X

对于Chandler的解释,请参阅以下链接,45分钟:

Clang:从Murphy的Million Monkeys中捍卫C ++

首先,我正确地假设成员变量n的零初始化是依赖于编译器实现的并且不是由标准保证(或者用c ++ 11进行了这种改变)?

不, 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

其次,为什么用C ++ 03而不是c ++ 11调用f(X)? 我假设f(void *)无论S()。n的值是否隐式转换为X,都会启动

在C ++ 03中, int永远不会成为空指针常量。 一旦0被输入为int ,比如将它赋给int ,那么它永远是一个int ,而不是一个空指针常量。

在C ++ 11, S().n是隐含一个constexpr表达值0 ,和constexpr与值表达式0可以是一个空指针常数。

最后,就我所知,这不是委员会的故意改变。 如果您正在编写依赖于这种差异的代码,那么如果/当委员会纠正自己时,您可能会在将来被咬。 我会很清楚这个领域。 用它来赢得赌注 - 而不是生产代码。

首先,对C ++ 03和C ++ 11的初始化规则进行一些澄清:

// This is default construction
S s;
// s.i has undefined value

// This is initialization from a value-initialized S (C++03 rules)
S s = S();
// s.i has been zero-initialized

// This is value initialization (C++11 rules)
// new syntax, better rules, same result
S s {};
// s.i has been zero-initialized

然后,记住int不能转换为void*所以在C ++ 03中f(S().n) 永远不会调用void f(void*); 即使没有其他f声明可用。

什么可能在C ++ 03是做f(0)这将调用void f(void*); 即使void f(X); 存在。 原因是int - > X转换(所谓的用户定义转换)不优于零积分常量 - > void*转换(不是UD转换)。 注意,也可以调用void f(void*); via f( (int()) )因为int()也是零积分常数,即使在C ++ 03中也是如此。 (像往常一样,括号在这里解决了语法模糊性。)

C ++ 11的变化是现在S().n是零积分常数。 原因是S()现在是一个常量表达式(由于广义常量表达式),这种成员访问也是如此。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM