C++ 用于循环退出条件(大小与整数)
当我在程序中加入以下内容时:C++ 用于循环退出条件(大小与整数),c++,for-loop,int,size-t,C++,For Loop,Int,Size T,当我在程序中加入以下内容时: 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 = VectorOfStru
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\u t
作为i
的类型,这是一个无符号类型,因此它永远不能有负值;这也意味着它不能与-1
但是(int)-1
被表示为0xFFFFFFFF
,它表示大小的一个相当大的数字(2^32-1
)i>0xFFFFFFFF
永远不可能为真,因为0xffffff
是size\u t
所能容纳的最大值
第三个示例使用了带符号int
(这允许使用负数,因此测试成功)
这一条应该有效:
for (size_t i = VectorOfStructs.size(); i-- > 0;) {
use(VectorOfStructs[i]);
}
size\u t
是无符号类型,因此-1
是size\u t
可以采用的最大值。在第二个代码段中,size\u t
不能大于此最大值,因此不会输入循环
另一方面,int
是一种有符号类型,因此与-1
的比较正如您所期望的那样
为什么第二个代码段无法执行
size\u t
是无符号的,因此根据定义,它从不为负。所以你的循环条件总是正确的。变量“环绕”到最大值。在第二个变量中,您将变量“i”与-1进行比较,这里它的类型是size\u 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\u t都是整数类型,但Int可以包含负数和正数。
int的范围为-2^31-1到2^31-1,而size\u t的范围为0到2^32-1
现在,当你写像int a=-1这样的东西时,它确实是-1,但是当你用size做的时候,你得到了max int 2^32-1
因此,在第二段代码中,任何大小的值都不会超过-1,因为它实际上是2^32-1
在第三个代码段中,比较的类型是int,当int与-1比较时,它会将其视为-1,因此当编译器看到i>-1
并注意到子表达式i
和-1
具有不同的类型时,它会将它们转换为公共类型。如果这两种类型(std::size_t
和int
)具有相同的位数(这对于编译器来说似乎是如此),则常见类型是无符号类型(std::size_t
)。所以这个表达式相当于i>(std::size\u t)-1
。但是当然(std::size_t)-1
是size_t
的最大可能值,因此比较总是错误的
大多数编译器都有一个关于比较的警告,因为这样的原因,比较总是正确的或错误的。每当比较“有符号”和“无符号”时,首先将“有符号”值转换为“无符号”。这包括(#1)和(#2),在“unsigned(0-1)”和“some unsigned”>“unsigned max”方面存在问题
但是,如果通过强制进行“有符号的”/“有符号的”比较(#3)使其工作,则失去了“无符号的”范围的1/2
你可以:
for(size_t n = vector.size(); n; /* no -- here */ ) {
--n;
// vector[n];
}
注意:无符号(-1)在许多系统上是最大的无符号整数值。size\u t是一种无符号类型,它永远不会大于(size\u t)-1
。大多数编译器都会为这类代码生成警告,您可能希望启用它。也许更好:for(auto-iter=VectorOfStructs.rbegin();iter!=VectorOfStructs.rend();++iter){/*使用*iter*/}
如果要向后迭代,您应该在for
循环的第二部分中检查i-->0
,并删除for循环的第三部分,尽管int
通常具有32位==4字节,早期机器使用2字节存储整数变量,但现在机器根据Systemsure的体系结构将其存储为2字节/4字节;这是非常罕见的这些天;顺便说一句,你能详细说明非物理内存是如何允许负大小的吗?不存在任何非物理内存,就好像你认为虚拟内存也有一些物理存在一样。啊,使用“->运算符”(参见相关的堆栈溢出问题) instead@BenjaminLindley:facepalm:/me不会再使用canonical…@KABoissonneault嘿,在你发表评论之前我已经修复了…你有“use()”函数的链接吗?我从没听说过,搜索结果一无所获。@Donald:那只是你代码的占位符!我不知道如何使用“*rit”。如果我这样做:int Counter=*rit;它给了我“错误:不存在从“VectorOfStructs”到“int”的可补转换函数”@Donald:迭代器允许您访问向量元素,而不是向量下标。