条件声明的变量的范围

塞巴斯蒂安·马赫

一些重构导致了一段代码,使我进入了这个最小的测试用例:

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章