将STL容器与迭代器一起使用有什么常见的误用?

时间:2009-02-03 12:23:00

标签: c++ stl iterator

STL容器与迭代器一起使用会有什么常见的误用?

9 个答案:

答案 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());