标准参考:int foo = foo 的含义是什么?

19

int foo = foo; 可以编译通过。C++标准的哪一部分允许这样做?


相关链接:https://dev59.com/RG035IYBdhLWcg3wYfAF - Lightness Races in Orbit
2个回答

26

3.3.1 声明点 [basic.scope.pdecl]

一个名称的声明点是在它的完整声明符之后(第8条款),初始化程序(如果有)之前立即发生。

如果声明位于文件作用域,则行为是定义良好的。如果您在函数作用域中声明,并且稍后使用foo [在这种情况下将被初始化为某些未指定的值],则行为将是未定义的。


4
我想点个赞,但你完全没有提到OP的程序存在未定义行为,因此不应该使用。 - Lightness Races in Orbit
5
@Tomalak说:代码可能存在未定义行为,但不一定。楼主似乎完全意识到这不是真正应该使用的东西,并且对它为什么能编译感到好奇,这是一个纯学术问题。 - Jerry Coffin
@Tomalak:不一定是未定义行为。OP并没有明确说明声明是在文件作用域还是函数作用域? - Prasoon Saurav
1
@Prasoon: s/program has/program may have/; s/should not/possibly should not/. - Lightness Races in Orbit
1
使用 foo “以后” 并不重要;初始化本身就会调用 UB!不是吗? - Lightness Races in Orbit
1
@Prasoon:没错,他在初始化中使用了它。他正在用未初始化的 B 来初始化 A(而且 AB 恰好是同一个对象)。 - Lightness Races in Orbit

21

这个?

int main() {
  int foo = foo;
}

根据[basic.scope.pdecl],在完整的声明符(第8条款)之后,变量名的声明点立即存在于其初始值(如果有)之前,因此foo对象在=之后确实存在。

然而,由于在右侧使用了未初始化的值,整个程序是未定义的:

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

并且:

尽管标准中"推断和规范不明确",对RHS表达式foo执行了一个左值到右值的转换

并且 ([conv.lval]):

非函数、非数组类型T的左值(3.10)可以转换为右值。如果T是不完整的类型,则需要进行此转换的程序是不良形式的。如果左值所引用的对象不是类型T的对象,也不是从T派生的类型的对象,或者如果对象未初始化,则需要进行此转换的程序具有未定义行为。

在适当的警告级别下,你将会收到相关的提示;然而,调用未定义行为的程序是允许编译的。只是当你运行它们时,它们可能会做任何事情。


或者,这个怎么样?

int foo = foo;    
int main() {}

请注意,foo 是一个"全局变量"。根据 [basic.start.init],它们在进行任何其他初始化之前首先进行零初始化:

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

因此,您将获得一个值为0的int foo;在这一点上,根据上面的[basic.scope.pdecl][stmt.decl],它是有效的:

所有具有静态存储期(3.7.1)的本地对象的零初始化(8.5)是在进行任何其他初始化之前执行的。[..]

然后,您将其值初始化为foo(它本身),即0。
这是明确定义的...如果有点难懂。

为了全面考虑,这里提供第三个也是最后一个案例:

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

不幸的是,这与第一种情况相同。由于当初始化器被评估时,局部变量foo已经声明并在作用域内,因此初始化器使用局部变量foo,你仍然会遇到未定义行为。全局变量foo没有被使用。


1
另一方面,如果它是全局的,则行为已定义。 - Jerry Coffin
@Jerry:我的程序中没有全局变量。如果OP的程序中有全局变量(或者他的foo声明发生在命名空间范围内),他需要说明这一点,因为这会完全改变问题的性质。 - Lightness Races in Orbit
@Jerry:好的,我会为那种情况添加一个子句。 - Lightness Races in Orbit
@Tomalak:标准是否规定初始化是未定义行为?(本地情况)。这很有道理,但我不记得有具体的规定。 - Matthieu M.
@Tomalak 是的,它就是这么说的 :) - Johannes Schaub - litb
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接