b1s*_*sub 12 c++ language-lawyer
根据标准(§3.3.3/ 4),N4567的标准禁止某些类型的重新声明先前在条件中声明的名称 - 如下:
在for-init-statement,for-range-declaration以及if,while,for和switch语句的条件中声明的名称是if,while,for或switch语句(包括受控语句)的本地名称,并且不得在该陈述的后续条件下,也不得在受控陈述的最外层(或if语句,任何最外层)中重新宣布; 见6.4.
但是,考虑到以下代码编译正常的事实,
int main(void) {
if (int i=10)
if (int i=20)
;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我似乎不清楚究竟"该陈述的后续条件"是什么代表什么.
突出显示的“that”语句表示已定义名称的if、while、for和switch语句,而不是由条件或迭代控制的子语句。
对此进行了解释:
6.4/3:由条件中的声明引入的名称(由 decl-specifier-seq 或条件的声明符引入)在从其声明点到条件控制的子语句末尾的范围内。如果在条件控制的子语句的最外层块中重新声明该名称,则重新声明该名称的声明格式错误。
这就是为什么以下陈述有效:
if (int i=10)
if (int i=20)
;
Run Code Online (Sandbox Code Playgroud)
编译器不会将 的声明分析为if (int i=20)同一 if 语句的不同条件,而是将其作为受控子语句进行分析。由于 i 的第二个声明发生在条件中,因此在受控语句的外部块中不考虑它。
相比之下,以下几乎等效的语句是无效的,因为它打破了外部块约束:
if (int k=10) {
int k=20; // <===== ouch ! redefinition in the outerblock
if (k)
cout <<"oops";
}
Run Code Online (Sandbox Code Playgroud)
因此,唯一可以拥有“该语句的后续条件”的情况就是该for语句。该标准通过用更清晰的措辞给出您引用的约束的基本原理来强调这种特殊情况:
6.5.3/1: (...) for-init-语句中声明的名称与条件中声明的名称位于同一声明区域中,
即在 init 和条件中声明相同的名称会破坏 ODR。