【问题标题】:C++ variable redeclaration within nested loops嵌套循环中的 C++ 变量重新声明
【发布时间】:2018-04-16 06:04:14
【问题描述】:

下面是一段带有 3 个嵌套循环的代码。变量 curs 和 tempv 在最外层 for 循环的每次迭代中都被重新声明。这应该给我错误,但我能够在 gcc 4.8.4 上成功运行它而不会出错。

for(int i = 0; i<lend; i++)
{
    string curs = vstring[digits[i]-'0'];
    vector<string> tempv;
    for(int j = 0; j<v.size(); j++)
    {
        for(int k = 0; k<curs.size(); k++)
        {
            tempv.push_back(v[j] + curs[k]);
        }
    }
    v = tempv;
}

在for循环中重新声明变量可以吗?我的理解是,在 C++ 中,不能在同一范围内重新声明变量。

【问题讨论】:

  • 每次迭代都会获得全新的对象。
  • 如果编译器说没问题,那没问题的。
  • 您只在循环范围内声明它们一次。每次迭代都会进入和离开范围。
  • @DyZ:不幸的是,一般而言在 C++ 中,它并不是衡量代码正确性或标准遵守情况的重要指标。有几个错误标准不需要任何诊断,或者他可能依赖于编译器特定的扩展。
  • 您确实使用了int j=0int k=0。您期望 jk 工作的方式,tempv 也可以这样工作

标签: c++ gcc syntax-error variable-declaration


【解决方案1】:

在for循环中重新声明变量可以吗?我的理解是,在 C++ 中,不能在同一范围内重新声明变量。

这是一个单一的词法作用域,这些变量在其中被声明一次。执行重复进入它的事实是无关紧要的 - 这并不像您在多次调用的函数中声明的变量出现重复定义错误。与往常一样,每次进入范围时,您都会获得其中定义的变量的新实例。

换句话说:作用域规则是关于程序的静态、词法结构,与程序的执行流程如何实际发生无关;它们充当其运行时行为的蓝图,因为它们指示编译器如何解析块的其余部分以及每次进入范围时要生成什么代码。

【讨论】:

    【解决方案2】:

    变量curstempv在最外层for循环的每次迭代中都被重新声明

    不,他们在每次迭代中都实例化。创建,并在块的末尾,销毁。由编译器完成的模优化。

    作用域是一个编译时概念。你通过检查代码看到的东西。实例化是一种运行时效果。相同的变量声明可以执行任意次数,实例化变量该次数。好吧,除非它是static,在这种情况下它会被实例化一次。

    我的理解是,在 C++ 中,不能在同一范围内重新声明变量。

    不能直接在同一范围内重新声明,但可以在嵌套范围内重新声明。而且您有许多嵌套范围。让我们考虑一下:

    for(int i = 0; i<lend; i++)                      // ← For loop scope.
    {                                                // ← Block scope.
        string curs = vstring[digits[i]-'0'];
        vector<string> tempv;
        for(int j = 0; j<v.size(); j++)              // ← For loop scope.
        {                                            // ← Block scope.
            for(int k = 0; k<curs.size(); k++)       // ← For loop scope.
            {                                        // ← Block scope.
                tempv.push_back(v[j] + curs[k]);
            }
        }
        v = tempv;
    }
    

    正式地,for 循环是定义的,它与放置在包含循环变量声明(如果有)的外部块中的相应while 循环的等价物。然而,

    C++17 §6.3.3/1:

    init-statementfor-range-declaration条件 中声明的名称>ifwhileforswitch 语句是 ifwhileforswitch 语句(包括受控语句)的本地语句, 并且不得在该语句的后续条件或最外层块中重新声明(或者,对于 受控语句的if 语句,任何最外层的块);见 9.4。

    例如,在您的代码中,外部 for 循环的 i 不能直接在构成该循环主体的块中重新声明,即使它是一个嵌套范围,但可以在内部嵌套循环中重新声明。

    【讨论】:

      【解决方案3】:

      这是完全合法的,事实上,它一直在使用。在这种情况下,每次迭代都可以被视为一个全新的范围。

      【讨论】:

        猜你喜欢
        • 2016-02-23
        • 1970-01-01
        • 2018-05-13
        • 1970-01-01
        • 2016-10-22
        • 2020-02-28
        • 2011-12-23
        • 2015-08-31
        • 2018-10-11
        相关资源
        最近更新 更多