2011-05-31 201 views
19

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

+0

相关:http://stackoverflow.com/questions/5450633/c-what-does-this-mean-int-foo-foo-4 – 2011-05-31 17:47:04

+0

另请参阅[初始化是否需要左值到右值的转换?是'INT X = X;'UB](http://stackoverflow.com/q/14935722/1708801)和[已C++标准相对于在C++ 14使用不定值和未定义的行为的改变]? (http://stackoverflow.com/q/23415661/1708801) – 2015-09-22 15:27:16

回答

26

3.3.1点声明[basic.scope.pdecl]

声明的一个名字的一点是后立即其完整说明符(第8节)和它的初始值设定前(如果有的话),

的行为,如果该声明是在文件范围是明确界定。如果你有在申报范围的功能,如果你使用foo稍后[这将被初始化为在这种情况下一些未指定值]的行为将是不确定的。

+4

我会+1,但你完全没有提到OP的程序有未定义的行为,并且不能使用_。 – 2011-05-31 14:40:47

+5

@Tomalak:代码*可能*有UB,但不一定。 OP似乎完全意识到这不是真的应该使用的东西,并且对它为什么编译的纯学术观点感到好奇。 – 2011-05-31 14:43:18

+2

@Jerry:仙女nuff。 – 2011-05-31 14:44:47

21

This?

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的类型的 对象,或者如果 对象是未初始化,即必要这种转换的程序 具有 未定义的行为。

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


或者,这个怎么样?

int foo = foo;  
int main() {} 

请注意foo是一个“全局”。这些是零初始化作为第一步,根据[basic.start.init]

具有静态存储的持续时间(3.7.1)的对象应是零初始化(8.5)任何其它初始化发生之前。

因此,您将得到一个值为0的int foo;它是有效的,在这一点上,按照[basic.scope.pdecl]上方,并且每[stmt.decl]为:

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

你那么如果有点神秘值初始化到foo(本身),即0。

这是良好定义...。


在彻底的利益,这里的第三和最后一种情况:

int foo = 42; 
int main() { 
    int foo = foo; 
} 

可悲的是,this is the same as the first case。由于本地foo已经宣布在由初始评估的时间范围,初始化使用本地foo和你仍然坚持与未定义行为。全局foo未使用。

+1

OTOH,如果它是一个全球性的,行为定义。 – 2011-05-31 14:41:41

+0

@Jerry:我的程序中没有全局变量。如果OP程序中有全局变量(或者他的'foo'声明发生在命名空间范围内),他需要说明这一点,因为它完全改变了问题。 – 2011-05-31 14:42:51

+0

@Jerry:好的。那么我也会为这种情况添加一个条款。 – 2011-05-31 14:46:23

相关问题