12

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

4

9 回答 9

21

如果您通过插入或删除容器成员来更改容器,请忘记迭代器通常会失效。

对于使用 STL 的许多重要提示,我强烈推荐 Scott Meyers 的书“Effective STL”(经过消毒的亚马逊链接

于 2009-02-03T12:26:29.153 回答
9

结束范围检查应该使用 != 而不是 < 因为不能保证指针的顺序。

例子:

for(it = list.begin(); it != list.end(); ++it)
{
     // do stuff
}
于 2009-02-03T12:47:25.430 回答
8

可以在预增量时进行后增量。

于 2009-02-03T12:36:47.930 回答
7

其他几个:

  • 将反向迭代器转换为基迭代器,而无需记住迭代器现在将是它所指向的元素之外的一个元素。

  • 尝试使用需要随机访问迭代器和集合和映射等迭代器的算法。

  • 使用非常量迭代器编辑映射条目的键(这恰好构建在 VS.Net 上,但不会使用 GCC)

于 2009-02-03T13:52:32.130 回答
6

在不阅读 Scott Meyers 的“Effective STL”书的情况下使用它们。:) 真的。这使得大多数愚蠢的错误消失了。

于 2009-02-03T13:17:02.483 回答
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;
    }
}

真的太多次了,我不得不在一些生产代码中应用这些修复:(

于 2009-02-03T14:19:10.377 回答
3

在容器内使用 auto_ptr,例如

list<auto_ptr<int> > foo;

幸运的是,现在编写了很多 auto_ptr 实现来使这成为不可能。

于 2009-02-03T14:36:20.093 回答
2

这不仅是 STL 容器的问题——在迭代容器时修改容器几乎总是会导致问题。

这是游戏中非常常见的错误来源——大多数游戏循环包括迭代每个游戏对象做某事。如果这个东西从游戏对象容器中添加或删除元素,几乎肯定有错误。

解决方案 - 有两个容器 - objectsToDelete 和 objectsToAdd - 在游戏代码中将对象添加到该容器,并仅在您迭代后更新游戏对象容器。

可以设置 objetsToAdd 以确保我们不会多次删除任何内容。

如果您可以构造 Object 而不将其添加到游戏对象容器中,则 objectsToDelete 可以是 Queue,或者如果您的代码假定 Object 实例总是在创建后直接添加到游戏对象容器中(例如在构造函数中),它可以是其他一些类(ObjectCreateCommand?) )。

于 2009-02-03T14:54:06.797 回答
1
list<int> l1, l2;
// ...

for_each(l1.begin(), l2.end(), do_it());
于 2009-02-03T22:06:47.233 回答