【问题标题】:Variables in scope during for loop iteration statement in C++C ++中for循环迭代语句期间范围内的变量
【发布时间】:2012-07-11 04:52:09
【问题描述】:

根据我对C++规范的理解(根据网上的标准草案),for循环可以改写为while循环和block用于初始化。根据我的理解,for-loop的迭代语句和body发生在同一个作用域,所以应该可以使用for-loop的body中声明的变量。 gcc 和 clang 都拒绝以下(人为的)代码,这是我真实代码的简化。

我显然可以通过在循环之外声明 j 来修复代码,但是为什么 j 超出了下面的范围?

int main() 
{
    for(int i=0; i<10; i=j) int j=i+1;

    // // I must misunderstand the standard because I thought the above loop is 
    // // equivalent to the commented code below where j is clearly in scope.
    // {
    //     int i=0;
    //     while(i<10) {
    //         int j=i+1;
    //         i=j;
    //     }
    // }

    return 0;
 }

根据clang(和gcc),这是无效的。

test.cpp:3:26: error: use of undeclared identifier 'j'
    for(int i=0; i<10; i=j) int j=i+1;
                         ^
1 error generated.

【问题讨论】:

  • 你在声明j之后你在i=j中使用它...while循环不会这样做。
  • 这是无效的语法,因为 j 直到在 for 循环内才被声明,尽管在第一个循环完成之前它没有被使用。
  • @nhahtdh,这就是我的意思。编译器还没有看到声明。什么时候使用在这方面是无关紧要的。
  • @chris:我的评论比你晚一点,所以它会通知你。不过,它不是针对你的。
  • @nhahtdh,啊,我把它误认为是“二手”这个词的迂腐,但这是真的。

标签: c++ scope language-lawyer specifications


【解决方案1】:
for(int i=0; i<10; i=j) int j=i+1;

如果它是有效的语法,将与

相同
for(int i=0; i<10; i=j) 
{
  int j=i+1;
}

for 循环然后访问 {} 范围内的“j”,直到执行第一个循环才存在。 C++ 是一种静态语言,它依赖于编译器能够在编译时解析其变量,但您正在做的是试图让它在运行时解析变量。

【讨论】:

  • 感谢您的回复。我同意您编写的代码等同于 for 循环,但我参考的标准草案进一步将您的代码重写为我在上面编写的 while 循环(open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf,第 111 页)。在 while-loop 版本中,j 显然在范围内。
  • 我认为你的回答实际上是正确的。我应该将我的代码转换为 {int i=0; while(i
  • @GManNickG 第 110 页,第 6.5 节第 2 段。“如果迭代语句中的子语句是单个语句而不是复合语句,就好像它被重写为复合语句一样——包含原始语句的语句。”
  • 这个答案听起来像是第一个 sn-p 在语法上不正确,尽管它是。然而,正如约翰对我的参考答案所评论的那样,第 6.5/2 节指出迭代语句周围有一个隐式块范围。
  • @GManNickG 你当然是对的,我的 sn-p 在语法上是有效的,但安德斯的回答似乎是最接近的。在重写为while循环形式之前,我没有执行body的重写。
【解决方案2】:

作为参考,展开如下(§6.5.3/1)。 for循环语句:

for (init cond; expr) statement

相当于:

{
    init
    while (cond)
    {
        statement
        expr;
    }
}

【讨论】:

  • 是的。我误解了“声明”的性质。具体来说,我必须根据 6.5 子语句 2 将它包含在一个块中。
【解决方案3】:

这是显而易见的。我给你举个例子。你能写出这样的东西吗?

int main(){
int i = j * 10;
//Some other lines ...
int j = 2;
return 0;
}

当然在给定的代码中 i 和 j 是在同一个范围内,但是在使用 j 之前你必须声明它。
除了范围之外,您还必须考虑其他事情。

【讨论】:

  • 他的代码中没有发生同样的情况,在扩展中循环表达式位于语句之后。
  • 好的,我修好了。但是,他必须考虑范围之外的其他事情。
【解决方案4】:

你得到错误的原因是因为'j'是在for循环中声明/初始化的。但是C++编译器是从左到右,从上到下编译的,所以当编译器遇到'i'被赋值为垃圾值时,会弹出错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    • 2011-11-24
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多