将 for 循环与向量一起使用时是否存在错误?
Is there a bug when using for loop with vectors?
问题是,当我执行 "for(int i = 0; i < vector.size() - 1; i++)" 时,它会给我一个 "vector subscript out of range" 错误。但是,如果我将 vector.size() - 1 放入变量中,它就可以工作。这是一个小故障还是我只是遗漏了什么?
这个有效:
int sizePos = positionsX.size() - 1;
for (int i = 0; i < sizePos; i++) {
if (snake.getX() == positionsX[i] && snake.getY() == positionsY[i]) {
gameOver = true;
std::cout << as << std::endl;
as++;
}
if (apple.getX() == positionsX[i] && apple.getY() == positionsY[i]) {
apple.eat();
}
}
而这不是:
for (int i = 0; i < positionsX.size() - 1; i++) {
if (snake.getX() == positionsX[i] && snake.getY() == positionsY[i]) {
gameOver = true;
std::cout << as << std::endl;
as++;
}
if (apple.getX() == positionsX[i] && apple.getY() == positionsY[i]) {
apple.eat();
}
}
positionsX.size()
是 unsigned
类型。如果它为零,则从中减去 1 会得到无符号类型的最大值,这是由于 wrap-around 以及表达式在无符号算术中求值的事实!
使用
for (std::size_t i = 0; i + 1 < positionsX.size(); i++) {
相反,这将始终忽略向量中的最后一个元素。如果你不想要那个然后删除 + 1
.
如果 positionsX
向量为空,则 positionsX.size() - 1
的计算结果为 size_t(-1)
,这是一个非常大的正值。
当转换为 int
时,如在您的第一个代码段中,该值可能会变回“-1”。并跳过循环体。
当用于比较 i < positionsX.size() - 1
时,编译器将 i
转换为无符号 size_t
并且比较结果为真。循环体被执行。它会尝试访问不存在的 positionsX[0]
...
您没有指出 "does not work" 是什么意思,在这种情况下代码不起作用。
尽管如此回答你的问题
Is there a bug when using for loop with vectors?
我会说代码确实有错误。
首先向量的大小被定义为无符号整数类型。 int
类型一般不能容纳无符号整数类型的所有值。
在这个表达式中
positionsX.size() - 1
这里用到了无符号整型的运算。也就是说,表达式 positionsX.size() - 1
被转换为无符号整数类型,并且将等于该类型的最大值,前提是 positionsX.size()
等于 0。即表达式实际上计算为
static_cast<decltype( positionsX )::size_type>( positionsX.size() - 1 );
例如,对于空向量,您可以获得以下结果
#include <iostream>
#include <vector>
int main()
{
std::vector<int> positionsX;
auto size = static_cast<decltype( positionsX )::size_type>( positionsX.size() - 1 );
std::cout << size << '\n';
}
控制台输出为
18446744073709551615
第一种使用中间变量的情况
int sizePos = positionsX.size() - 1;
表达式的结果
positionsX.size() - 1
可以被截断以适应 int
类型的对象,并且相应的索引将有效(尽管范围可能完全无效,因为它可能小于实际范围)。
因此您的问题是您使用的是类型 int
而不是原始类型
decltype( positionX )::size_type
循环也省略了向量的最后一个元素。
正确的循环如下所示
for (decltype( positionX )::size_type i = 0; i < positionsX.size(); i++) {
//...
}
或者至少你应该使用类型 size_t 作为变量的类型 i
(尽管第一个变体更正确)
for ( size_t i = 0; i < positionsX.size(); i++) {
//...
}
问题是,当我执行 "for(int i = 0; i < vector.size() - 1; i++)" 时,它会给我一个 "vector subscript out of range" 错误。但是,如果我将 vector.size() - 1 放入变量中,它就可以工作。这是一个小故障还是我只是遗漏了什么?
这个有效:
int sizePos = positionsX.size() - 1;
for (int i = 0; i < sizePos; i++) {
if (snake.getX() == positionsX[i] && snake.getY() == positionsY[i]) {
gameOver = true;
std::cout << as << std::endl;
as++;
}
if (apple.getX() == positionsX[i] && apple.getY() == positionsY[i]) {
apple.eat();
}
}
而这不是:
for (int i = 0; i < positionsX.size() - 1; i++) {
if (snake.getX() == positionsX[i] && snake.getY() == positionsY[i]) {
gameOver = true;
std::cout << as << std::endl;
as++;
}
if (apple.getX() == positionsX[i] && apple.getY() == positionsY[i]) {
apple.eat();
}
}
positionsX.size()
是 unsigned
类型。如果它为零,则从中减去 1 会得到无符号类型的最大值,这是由于 wrap-around 以及表达式在无符号算术中求值的事实!
使用
for (std::size_t i = 0; i + 1 < positionsX.size(); i++) {
相反,这将始终忽略向量中的最后一个元素。如果你不想要那个然后删除 + 1
.
如果 positionsX
向量为空,则 positionsX.size() - 1
的计算结果为 size_t(-1)
,这是一个非常大的正值。
当转换为 int
时,如在您的第一个代码段中,该值可能会变回“-1”。并跳过循环体。
当用于比较 i < positionsX.size() - 1
时,编译器将 i
转换为无符号 size_t
并且比较结果为真。循环体被执行。它会尝试访问不存在的 positionsX[0]
...
您没有指出 "does not work" 是什么意思,在这种情况下代码不起作用。
尽管如此回答你的问题
Is there a bug when using for loop with vectors?
我会说代码确实有错误。
首先向量的大小被定义为无符号整数类型。 int
类型一般不能容纳无符号整数类型的所有值。
在这个表达式中
positionsX.size() - 1
这里用到了无符号整型的运算。也就是说,表达式 positionsX.size() - 1
被转换为无符号整数类型,并且将等于该类型的最大值,前提是 positionsX.size()
等于 0。即表达式实际上计算为
static_cast<decltype( positionsX )::size_type>( positionsX.size() - 1 );
例如,对于空向量,您可以获得以下结果
#include <iostream>
#include <vector>
int main()
{
std::vector<int> positionsX;
auto size = static_cast<decltype( positionsX )::size_type>( positionsX.size() - 1 );
std::cout << size << '\n';
}
控制台输出为
18446744073709551615
第一种使用中间变量的情况
int sizePos = positionsX.size() - 1;
表达式的结果
positionsX.size() - 1
可以被截断以适应 int
类型的对象,并且相应的索引将有效(尽管范围可能完全无效,因为它可能小于实际范围)。
因此您的问题是您使用的是类型 int
而不是原始类型
decltype( positionX )::size_type
循环也省略了向量的最后一个元素。
正确的循环如下所示
for (decltype( positionX )::size_type i = 0; i < positionsX.size(); i++) {
//...
}
或者至少你应该使用类型 size_t 作为变量的类型 i
(尽管第一个变体更正确)
for ( size_t i = 0; i < positionsX.size(); i++) {
//...
}