必须为第二个 for 循环重新声明一个 int

Having to redeclare an int for a second for loop

我正在玩 edabit.com C++ 挑战来刷新自己,我遇到了一个挑战,我需要编写一个函数,给定一个向量,return true if all even索引是偶数,所有奇数索引都是奇数。否则 return 错误。该功能的逻辑和一切都很好。我知道有几种方法可以做到这一点,但想出了一个(我认为)创造性的解决方案,而不是 运行 通过一个 for 循环检查索引是奇数还是偶数,我改为写了两个后续的 for 循环每个增加两个。一个从 0 开始,另一个从 1 开始。一旦发现不匹配,它就会 return 为 false。否则最后它将 return 为真。我来自 JavaScript,在那里你不需要重新声明索引变量(如果使用 var 而不是 let)但是这段代码编译失败:

bool isSpecialArray(std::vector<int> arr) {
    for(int i = 0; i < arr.size(); i = i + 2){
        if(arr[i] % 2 == 1){
            return false;
        }
    }

    for(i = 1; i < arr.size(); i = i + 2){
        if(arr[i] % 2 == 0){
            return false;
        }
    }

    return true;
}

说明:

error: use of undeclared identifier 'i'
        for(i = 1; i < arr.size(); i = i + 2){
            ^

当然,在第二个 for 循环中声明 int 清除了错误,程序按预期执行。我猜这是由于垃圾回收,但标准中是否有特定规则来定义它?或者这可能是每个编译器的事情?我对垃圾回收的理解是,一旦声明的变量不会从内存中清除,直到不再在定义它的当前函数中使用。这是否因 for 循环的范围而不同,类似于 JavaScript的let

C++ 中没有垃圾回收,即使有,也不能解释你的错误。实际原因很简单:声明为 for 循环一部分的变量在循环后超出范围。

c++ 没有垃圾回收。相反,它会确定性地破坏对象,例如 i。编译器执行此操作的方式是在对象所在的作用域结束后清理该对象,然后不允许您使用该对象。

int main() 
{
 {
  int i;
 } // scope of i ends

 cout << i; // error, can't access i here
}

for 循环有自己的作用域,因此在您的示例中,第一个循环中的 i 在第二个循环中不可访问。

首先,JS 和 C++ 的作用域模型非常不同,而 JS 以其糟糕的做法而闻名(抱歉)。在 C++ 中,规则更加一致:只要程序退出作用域,变量就会被销毁。这意味着在这段代码中:

for (int i = 0; ; ) {
}

变量 i 仅为此作用域定义,不能在另一个(非嵌套)循环中重复使用,在其他地方看不到,并且名称可以在内部作用域中重复使用或重新定义。这给您带来的优势是更容易控制数据缺陷并减少副作用。所以你的解决方案是在第二个循环中声明另一个变量i

    for(int i = 1; i < arr.size(); i = i + 2){
        if(arr[i] % 2 == 0){
            return false;
        }
    }

只要你是JS界的,我会给你更多的推荐。首先,不要按值传递向量(除非您意识到自己在做什么)。通过引用传递它,或者通过 const 引用传递它更好:

bool isSpecialArray(const std::vector<int> &arr) {
   // ...
}

接下来,一种可能更有效、更惯用的增加索引的方法是 i += 2

最后的观察:您的解决方案中没有 "creativity",但也有缺点。此代码变得不太缓存友好,这可能被认为是一种不好的做法。

您程序中的变量 i 是在块或花括号 ({ }) 内声明的。因此,变量 i 是一个 局部变量 ,只能在该块内使用。

bool isSpecialArray(std::vector<int> arr) {
    int i;
    for(i = 0; i < arr.size(); i = i + 2){
        if(arr[i] % 2 == 1){
            return false;
        }
    }

    for(i = 1; i < arr.size(); i = i + 2){
        if(arr[i] % 2 == 0){
            return false;
        }
    }

    return true;
}

这是正确的做法。