将STL容器与迭代器一起使用会有什么常见的误用?
答案 0 :(得分:21)
如果通过插入或删除容器成员来更改容器,则忘记迭代器经常失效。
关于使用STL的许多重要提示我高度推荐Scott Meyers的书“Effective STL”(sanitised Amazon link)
答案 1 :(得分:9)
结束范围检查应使用!=而不是<因为指针的顺序无法保证。
示例:
for(it = list.begin(); it != list.end(); ++it)
{
// do stuff
}
答案 2 :(得分:8)
预增量时的后递增。
答案 3 :(得分:7)
其他一些人:
将反向迭代器转换为基本迭代器,而不记住迭代器现在将是它指向的迭代器之外的一个元素。
尝试使用需要随机访问迭代器的算法以及集合和映射之类的迭代器。
使用非const迭代器编辑映射条目的键(这恰好构建在VS.Net上,但不适用于GCC)
答案 4 :(得分:6)
使用它们而不阅读Scott Meyers的“Effective STL”一书。 :)真的。这使得大多数愚蠢的错误都消失了。
答案 5 :(得分:6)
erase()
之后的正确继续。
假设:
Container::iterator i = cont.begin(), iEnd = cont.end();
例如在std::map
上,这不是一个好主意:
for (; i != iEnd; ++i) {
if (i->second.eraseCondition()) {
cont.erase(i);
}
}
这样可行:
for (; i != iEnd; ) {
Container::iterator temp = i;
++temp;
if (i->second.eraseCondition()) {
cont.erase(i);
}
i = temp;
}
这也是:
for (; i != iEnd; ) {
if (i->second.eraseCondition()) {
cont.erase(i++);
}
else {
++i;
}
}
实际上,我必须在某些生产代码中应用这些修补程序已经太多次了:(
答案 6 :(得分:3)
在容器内使用auto_ptr,例如
list<auto_ptr<int> > foo;
幸运的是,现在编写了很多auto_ptr实现,以使其无法实现。
答案 7 :(得分:2)
这不仅仅是STL容器的问题 - 迭代它时的容器也几乎总会导致问题。
这是游戏中常见错误的常见来源 - 大多数游戏循环包括迭代每个游戏对象做某事。如果这个东西增加或删除了游戏对象容器中的元素,几乎肯定会有bug。
解决方案 - 在游戏代码中有两个容器 - objectsToDelete和objectsToAdd - 将对象添加到容器中,并在迭代后更新游戏对象容器。
objetsToAdd可以设置为确保我们不会删除任何超过一次。
objectsToDelete可以是Queue,如果你可以构造Object而不将它添加到游戏对象容器中,或者它可以是其他类(ObjectCreateCommand?),如果你的代码假定Object实例总是在创建后直接添加到游戏对象容器中(对于构造函数中的示例。)
答案 8 :(得分:1)
list<int> l1, l2;
// ...
for_each(l1.begin(), l2.end(), do_it());