Pra*_*rav 26
3.3.1声明点[basic.scope.pdecl]
名称的声明点紧接在其完整的声明者(第8条)之后和其初始化者(如果有的话)之前,
如果声明位于文件范围,则行为已明确定义.如果您在函数范围内有声明,并且foo稍后使用[在这种情况下将初始化为某些未指定的值],则行为将是未定义的.
Lig*_*ica 21
这个?
int main() {
int foo = foo;
}
Run Code Online (Sandbox Code Playgroud)
该对象foo确实存在之后=,根据[basic.scope.pdecl]:
名称的声明点紧跟在其完整的声明符(第8节)之后和其初始化器之前(如果有的话).
但是,整个程序是未定义的,因为您使用(在RHS上)未初始化的值:
int x = x;这里[..]x用它自己的(不确定的)值初始化.
和:
虽然"推断和虐待指定"由标准,一个左值到右值转换是在RHS表达式进行的foo.
和([conv.lval]):
可以将非函数非数组类型T的左值(3.10)转换为右值.如果T是不完整类型,则需要进行此转换的程序格式不正确.如果左值引用的对象不是类型T的对象,并且不是从T派生的类型的对象,或者如果对象未初始化,则需要此转换的程序具有未定义的行为.
有了适当的警告级别,你就会被告知 ; 但是,允许编译调用未定义行为的程序.当你运行它们时,它们可以做任何事情.
或者,这个呢?
int foo = foo;
int main() {}
Run Code Online (Sandbox Code Playgroud)
请注意,这foo是一个"全球".根据以下内容,这些是零初始化的第一步[basic.start.init]:
具有静态存储持续时间(3.7.1)的对象应在任何其他初始化发生之前进行零初始化(8.5).
所以你得到的int foo值是0; 在这一点上,它是有效的,[basic.scope.pdecl]如上所述,并按照[stmt.decl]:
具有静态存储持续时间(3.7.1)的所有本地对象的零初始化(8.5)在任何其他初始化发生之前执行.[..]
然后将值初始化为foo(自身),即0.
这是明确定义的...如果有点神秘.
为了彻底,这是第三个也是最后一个案例:
int foo = 42;
int main() {
int foo = foo;
}
Run Code Online (Sandbox Code Playgroud)
可悲的是,这与第一种情况相同.由于在foo初始化程序计算之前已经声明了本地并且在范围内,因此初始化程序使用本地,foo并且您仍然处于未定义行为状态.全局foo未使用.
| 归档时间: |
|
| 查看次数: |
540 次 |
| 最近记录: |