一些重构导致了一段代码,使我得到了这个最小的测试用例:
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 Selection statements [stmt.select]
A name introduced by a declaration in a condition (either introduced by the
type-specifier-seq
or the declarator of the condition) is in scope from its point of declaration until the end of the substatements controlled by the condition. If the name is re-declared in the outermost block of a substatement controlled by the condition, the declaration that re-declares the name is ill-formed. [ Example:if (int x = f()) { int x; // ill-formed, redeclaration of x } else { int x; // ill-formed, redeclaration of x }
— end example ]
(强调我的)
这基本上意味着 i
的范围从条件开始,并在 if
block 之后结束,其中 else
block 也是 if
block 的一部分。
嵌套 if
的第二个问题是基于(错误的)假设 else-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
声明在 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;
}
}
所以总而言之,不要 panic :使用在最后一条语句中找到的模式编写分词器或解析器或其他东西仍然有效,这里相关的新知识是条件中的任何声明跨越整个 if
-tree,但可以在任何嵌套的 if
中覆盖。
此外,请确保以下内容仍然无效(即使它在旧编译器中有效):
if (int i=0) {}
std::cout << i; // nope, not valid
关于c++ - 条件中声明的变量范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18225721/