int foo = foo的标准参考

时间:2011-05-31 14:28:21

标签: c++ undefined-behavior

int foo = foo;编译。 C ++标准的哪一部分允许这个?

2 个答案:

答案 0 :(得分:26)

  

3.3.1声明点[basic.scope.pdecl]

     

名称的声明点紧跟在完整的声明者(第8条)之后和初始化者之前(如果有的话),

如果声明位于文件范围,则行为已明确定义。如果您在函数范围内有声明,并且稍后使用foo [在这种情况下将初始化为某些未指定的值],则行为将是未定义的。

答案 1 :(得分:21)

此?

int main() {
  int foo = foo;
}

根据foo=之后的对象[basic.scope.pdecl]确实存在:

  

名称的声明点在其完整声明者(第8条)之后立即,在其初始化程序之前 (如果有)。

但是,整个程序是未定义的,因为您使用(在RHS上)未初始化的值:

  

int x = x;   这里[..] x用自己的(不确定的)值初始化。

虽然标准an lvalue-to-rvalue conversion is performed on the RHS expression foo已经“推断并且不明确”。

和([conv.lval]):

  

非功能的左值(3.10),   非数组类型T可以转换为   一个右值。如果T是不完整的类型,   一个需要这个的程序   转换是不正确的。如果   左值所指的对象   不是T类型的对象而不是   从T派生的类型的对象,或 if   该对象未初始化,是一个程序   这需要这种转换   未定义的行为。

有适当的警告级别you will get told about it;但是,允许编译调用未定义行为的程序。当你运行它们时,它们可以做任何事情。


或者,这个怎么样?

int foo = foo;    
int main() {}

请注意foo是“全局”。根据{{​​1}}:

,这些是零初始化的第一步
  

具有静态存储持续时间(3.7.1)的对象应在进行任何其他初始化之前进行零初始化(8.5)

所以你得到一个值{0}的[basic.start.init];此时,根据上面的int foo[basic.scope.pdecl],它是有效的:

  

所有的零初始化(8.5)   具有静态存储的本地对象   持续时间(3.7.1)之前执行   发生任何其他初始化。 [..]

然后将其值初始化为[stmt.decl](本身),即0。

这是明确定义的...如果有点神秘。


为了彻底,这是第三个也是最后一个案例:

foo

可悲的是,this is the same as the first case。由于本地int foo = 42; int main() { int foo = foo; } 已在声明初始化程序时已声明并且在范围内,因此初始值设定项使用本地foo并且您仍然遇到未定义行为。

}未使用全球foo