一些重构导致了一段代码,使我进入了这个最小的测试用例:
int main () {
if (int i=1) {
/* IF-BLOCK */
} else {
throw i;
}
}
这样编译就可以了。但是,我一直以为i
仅对可见IF-BLOCK
,但似乎不可见。这是编译器错误吗?
另外,为什么下面的工作?
int main () {
if (int i=1) {
} else if (int i=2) {
} else {
throw i;
}
}
注意第二个if
“重新声明” i
。另一个编译器错误?
不,这实际上是正确的行为。
6.4选择语句[stmt.select]
由条件中的声明引入的名称(由条件
type-specifier-seq
的声明者或条件的声明者引入)从其声明的角度一直到该条件所控制的子语句的末尾。如果名称重新声明在最外层块由条件,控制的子语句的声明是重新声明的名称是形成不良。[ 例子:if (int x = f()) { int x; // ill-formed, redeclaration of x } else { int x; // ill-formed, redeclaration of x }
—结束示例]
(强调我的)
从根本上讲,这意味着i
条件的范围从条件开始,在if
-block之后结束,其中else
-block也是-block的一部分if
。
嵌套的第二个问题if
是基于(错误)的假设,即anelse-if
是介绍的一部分if
,但实际上并非如此。该if (int i=2)
是第一的身体else
!
if (int i=1)
|
/ \
/ \
/ \
/ \
/ \
if-block else
|
if(int i=2)
/ \
/ \
/ \
if-block throw i
这又意味着什么:
int main () {
if (int i=1) {
} else if (1) {
throw (i+2);
} else {
throw i;
}
}
这段代码是有效的,因为i
-declaration在中是可见的throw (i+2);
,但是隐藏第一个仍是有效的i
,因为在嵌套作用域中,名称可以被覆盖:
int main () {
if (int i=1) {
} else if (int i=2) {
throw (i+2); // now refers to `int i=2`
} else {
throw i;
}
}
因此总而言之,不要惊慌:使用最后一条语句中的模式编写令牌化程序或解析器或其他内容仍然有效,这里的相关新知识是条件中的任何声明if
都可以覆盖整个-tree,但可以在其中覆盖任何嵌套的if
。
另外,请确保以下内容仍然无效(即使在旧的编译器中有效):
if (int i=0) {}
std::cout << i; // nope, not valid
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句