nic*_*ole 14 c++ int vector size-t
所以我在一个程序中有一个普通的for循环通过一个对象向量(对象是我定义的类型,如果相关的话):
for(int k = 0; k < objects.size(); k++){ ... }
Run Code Online (Sandbox Code Playgroud)
...当我编译时,我得到这个警告:
warning: comparison between signed and unsigned integer expressions
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为我认为size()
一个向量返回一个size_t
.但为什么重要呢?不是一定数量的元素(甚至是内存块)是一个可以计算的整数吗?更重要的是,由于我的程序有多个这样的循环并且发生了很多段错误,这可能是它的一部分吗?
Gre*_*ill 11
object.size()
返回一个大于最大可表示值的k
值时会出现问题.自k
签名以来,与size_t
1相比,它只有最大值的一半.
现在,这可能不会发生在您的特定应用程序中(在典型的32位系统上,您的集合中将有超过20亿个对象),但使用正确的类型总是一个好主意.
1.先发制人的反驳:是的,这仅适用于使用典型二进制补码算法的机器,int
以及size_t
使用相同位数表示的机器.
ric*_*ici 11
已经很好地回答了,但我会添加我的S/0.02:"正确"的方法是:
for (typename std::vector<MyObject>::size_type i = 0; i < object.size(); ++i) { ... }
Run Code Online (Sandbox Code Playgroud)
只有有抱负的语言律师会写这个,甚至他们可能会在他们找到好东西之前停止阅读.
使用C++ 11,您可以利用decltype
:
for (decltype(object.size()) i = 0; i < object.size(); ++i) { ... }
Run Code Online (Sandbox Code Playgroud)
或者你可以利用auto
:
for (auto i = object.size() - object.size(); i < object.size(); ++i) { ... }
Run Code Online (Sandbox Code Playgroud)
或者您可以使用size_t
,但您仍然可能对溢出有疑问,因为vector<MyObject>
size_type可能大于size_t.(不是,但没有保证):
for (size_t i = 0; i < object.size(); ++i) { ... }
Run Code Online (Sandbox Code Playgroud)
那么一个诚实的程序员要做什么?
绝对最简单的解决方案是STL从一开始就一直在推广的解决方案.除了在开始之外,写作也是一种痛苦:
for (typename std::vector<MyObject>::iterator_type it = object.begin(); it != object.end(); ++it) { ... }
Run Code Online (Sandbox Code Playgroud)
现在,C++ 11确实对你有帮助.你有一些非常好的选择,从简单开始:
for (auto it = object.begin(); it != object.end(); ++it) { ... }
Run Code Online (Sandbox Code Playgroud)
但它变得更好(鼓,请)...:
for (auto& val : object) { ... }
Run Code Online (Sandbox Code Playgroud)
这就是我使用的那个.
编辑添加:
Cory Nelson在评论中指出,也可以将object.end()的结果缓存为:
for (auto it = object.begin(), end = object.end(); it != end; ++it) { ... }
Run Code Online (Sandbox Code Playgroud)
事实证明,for (var : object)
语法生成的代码与Cory Nelson提出的代码非常相似.(所以我鼓励他和你只使用后者.)
然而,这与其他语义略有不同,包括作为原始帖子主题的迭代.如果您在迭代期间以改变其大小的方式修改容器,那么您必须仔细考虑事情.灾难很有可能发生.
迭代可能在迭代期间被修改的向量的唯一方法是使用整数索引,如在原始帖子中那样.其他容器更宽容.您可以使用循环迭代STL映射,该循环在每次迭代时调用object.end(),并且(据我所知)它甚至可以在插入和删除时使用,但是不要尝试使用unordered_map,或矢量.如果你总是在末端推动并在前面弹出,它确实可以使用双端队列,如果你在广度优先的步行中使用双端队列作为队列,这很方便; 我不确定你能不能在后面弹出双端队列.
在迭代器和元素指针(它们并不总是与迭代器相同)的容器类型容器类型的影响下,确实应该有一个简单的总结,因为这都是标准规定的,但我从来没有碰到它任何地方.如果你找到一个,请告诉我.
归档时间: |
|
查看次数: |
2773 次 |
最近记录: |