For 循环退出条件(size_t vs. int)

For Loop Exit Condition (size_t vs. int)

当我将以下内容放入我的程序中时:

for (size_t i = VectorOfStructs.size()-1; i > 0; i--)

它工作正常,但 "i" 永远不会等于 0。 因此,我无法访问第一个元素 (VectorOfStructs[0])。

如果我把它改成:

for (size_t i = VectorOfStructs.size()-1; i > -1; i--)

程序甚至没有进入for循环!但是,如果我将其更改为以下内容:

for (int i = VectorOfStructs.size()-1; i > -1; i--)

它完全符合我的要求(遍历所有元素)。

所以,我的问题是:

(A)为什么第二个代码片段执行失败?

(B) 为什么第三个代码片段相应地执行而第二个代码片段没有执行?

任何见解将不胜感激!

第二个例子使用size_t作为i的类型,这是一个unsigned类型,因此它永远不能有负值;这也意味着它不能与 -1

进行正确比较

但是 (int)-1 被位表示为 0xFFFFFFFF,这代表 size_t 相当大的数字 (2^32-1)。 i>0xFFFFFFFF 永远不可能为真,因为 0xFFFFFFFsize_t 可以容纳的最大值。

第三个示例使用 signed int(允许负数,因此测试成功)。

这个应该有效:

for (size_t i = VectorOfStructs.size(); i-- > 0;) {
  use(VectorOfStructs[i]);
}

size_t 是无符号类型,所以 -1size_t 可以取的最大值。在第二个代码段中,size_t 不能大于此最大值,因此不会进入循环。

另一方面,int 是有符号类型,因此与 -1 的比较如您所料。

Why does the 2nd code snippet fail to execute?

size_t 是无符号的,因此根据定义它永远不会为负数。所以你的循环条件总是正确的。变量"wraps around"到最大值。

在第二个中,您将变量 'i' 与 -1 进行比较,此处它的类型为 size_t 并且大小不能为负数,因此失败。

第三个,'i'是整数类型,整数的范围是-32568到+32567(对于系统中的int=2字节)

整体size_t变量不能有负值,因为物理内存会在系统中存在

所有循环都向前,即使是向后循环。

你想要的是:

for (std::size_t i = 0, e = VectorOfStructs.size(); i != e; ++i)
{
    std::size_t const ri = e - i - 1;

    // use "VectorOfStructs[ri]"
}

或更好:

for (auto rit = VectorOfStructs.rbegin(); rit != VectorOfStructs.rend(); ++rit)
{
    // use "*rit"
}

(你的第二个片段失败,因为 i 是无符号的,所以 -1 被转换为与 i 相同的类型并成为最大可表示值,所以比较总是正确的.相比之下,i在第三个片段中签名。)

Int 和 size_t 都是整数类型,但 int 可以包含负数和正数。 int 范围从 -2^31 -1 到 2^31 -1 而 size_t 范围从 0 到 2^32 -1

现在,当你写类似 int a = -1 的东西时,它确实是 -1 但当你用 size_t 这样做时,你会得到 max int 2^32 -1

所以在第二个片段中没有 size_t 值会超过 -1 因为它真的是 2^32 -1

在第 3 个片段中,比较的类型是 int,当将 int 与 -1 进行比较时,它会将其视为 -1,因此它会按您计划的方式执行

当编译器看到 i > -1 并注意到子表达式 i-1 具有不同的类型时,它会将它们都转换为 通用类型.如果这两种类型(std::size_tint)具有相同的位数(您的编译器似乎就是这种情况),则常见类型是无符号类型 (std::size_t)。所以表达式结果等价于 i > (std::size_t)-1。但是当然 (std::size_t)-1 是一个 size_t 的最大可能值,所以比较总是假的。

大多数编译器都会发出警告,指出出于此类原因,比较始终为真或始终为假。

每当您比较 'signed' 和 'unsigned' 时,'signed' 值首先会转换为 'unsigned'。这涵盖了 (#1) 和 (#2),'unsigned(0-1)' 和 'some unsigned' > 'unsigned max'.

有问题

但是,通过强制进行 'signed'/'signed' 比较(#3)使其工作,您失去了 'unsigned' 范围的 1/2。

你可以这样做:

for(size_t n = vector.size(); n; /* no -- here */ ) {
   --n;
   // vector[n];
}

注意:unsigned(-1) 在许多系统上是最大的无符号整数值。