2012-03-01 40 views
4

我刚才看了钱德勒对锵介绍,在融入本土2012他提出了下面的代码:默认构造函数,POD的初始化和隐式类型转换在C++ 11

#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

对于钱德勒的说明,请参见下面的链接,在45分钟内:

Clang: Defending C++ from Murphy's Million Monkeys

回答

9

首先是吗在假定零初始化构件 变量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 

其次为什么F(X)与C++ 03,而不是C++ 11叫什么名字?的 我假定F(无效*)将踢无论S的值()。1. 以上的隐式转换到X

在C++ 03的int永远不能成为一个空指针不变。一旦0被键入为int,例如通过将其分配给int,那么它永远是int,而不是空指针常量。

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

最后,就我所知,这不是委员会的故意改变。如果你正在编写依赖于这种差异的代码,那么如果/当委员会自行修正的时候,你很可能会在未来陷入困境。我会避开这个区域。用它来赢得酒吧投注 - 而不是生产代码。

+0

您是否知道缺陷报告是否已在此提交?我没有看到,但我可能错过了它。 – bames53 2012-03-01 17:04:22

+0

谢谢,我永远不会写这样的代码,只是在观看钱德勒的演示文稿后感兴趣... – mark 2012-03-01 17:38:03

+0

啊NVM我现在看到用“int”表示“你的意思是一个int变量”。我很困惑,并认为你的意思是说“0”不是int,或者int表达式永远不能是空指针常量。 – 2012-03-01 20:35:42

5

首先,一些澄清在初始化两个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);存在。原因在于- >X转换(所谓的用户定义的转换)并不优于零积分常量 - >void*转换(这不是UD转换)。请注意,也可以通过f((int()))调用void f(void*);,因为int()也是一个零积分常量,即使在C++ 03中也是如此。 (像往常一样,括号在这里解决语法歧义。)

C++ 11改变的是现在S().n是一个零积分常数。原因是S()现在是一个常量表达式(感谢概括常量表达式),并且这种成员访问也是。

相关问题