c++ - 条件中声明的变量范围

标签 c++ scope

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

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/

相关文章:

java - 在 JNI 中从 C++ 代码创建 New<PrimitiveType>Array 时如何释放 <PrimitiveType>Array 的缓冲区?

c++ - Qt 5.5 - 触摸屏事件仅在初始(第一个)窗口中工作

c++ - C/C++ 头文件和实现文件 : How do they work?

perl - 如何祝福传递给子程序的列表中的对象?

python - 首次使用后重新分配时局部变量上的 UnboundLocalError

c++ - 使用 const 成员分配类

c++ - 数据成员 int 引用

javascript - AngularJS $scope 更新未反射(reflect)在 View 中

javascript - AngularJs 在 Controller 和 Controller 之间共享 $scope

java - 返回语句中的 "error: cannot find symbol"