必须为第二个 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;
}
这是正确的做法。
我正在玩 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;
}
这是正确的做法。