我在edabit.com C ++挑战中玩耍以刷新自我,我面临一个挑战,在这个挑战中,我需要编写一个函数,给定一个向量,如果所有偶数索引均为偶数且所有奇数索引均为奇数,则返回true 。否则返回false。逻辑和功能的一切都很好。我知道有几种方法可以做到这一点,但是想出了一个(我认为)创造性的解决方案,而不是通过检查索引是否为奇数或偶数来运行一个for循环,而是编写了两个后续的for循环,这些循环以2为增量每。一个从0开始,另一个从1开始。一旦发现不匹配,则返回false。否则最后它将返回true。我来自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
?
for
循环一部分的变量在循环后超出范围。 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
。以及最后的观察:您的解决方案中没有“创造力”,但是有缺点。此代码对缓存的友好程度降低了,这可能被认为是不好的做法。
i
)进行确定性销毁。编译器执行此操作的方法是,一旦对象的作用域结束,便清理该对象,然后再不允许您使用该对象。int main()
{
{
int i;
} // scope of i ends
cout << i; // error, can't access i here
}
for
循环具有自己的范围,因此在您的示例中,第一个循环中的i
在第二个循环中不可访问。