2

我正在开发一个应用程序,我在其中绘制了几张图像,如下所示:

void TimeSlice::draw(float fX, float fY) {
list<TimeSliceLevel*>::iterator it = levels.begin();
float level_x = x;
float level_y = y;
while(it != levels.end()) {
    (*it)->draw(level_x,level_y);
    level_y += (*it)->height;
    ++it;
}

}

虽然这有点不正确。我需要将 TimeSliceLevel* 放在 X 上。当我有一个for(int i = 0; i < slices.size(); ++i)循环时,我可以使用x = i * width. 虽然我正在使用迭代器,因为我多次被告知这是一个很好的编程:> 我想知道迭代器是否有一个“索引”数,我可以用它来计算新的 X 位置?(所以更多的是关于使用迭代器的问题)

亲切的问候, Pollux

4

6 回答 6

7

它们不会,因为迭代器除了从有序索引列表的开头循环到结尾之外,还可以用于其他目的。您需要单独跟踪索引并在每次传递时递增它:

list<TimeSliceLevel*>::iterator it;
int index;

for(it = levels.begin(), index = 0; it != levels.end(); ++it, ++index) {
    ...
}
于 2010-06-12T18:19:10.607 回答
3

不,它没有。如果需要整数索引,请使用 for 循环。尽管某些迭代器极端主义者会让您相信,但 for 循环仍然在 C++ 代码中占有一席之地。

于 2010-06-12T18:18:35.403 回答
2

可以从迭代器 -> 索引。至少有两种方式:

  1. 用于-随机访问迭代器(即i - container.begin()
  2. 使用std::distance(即std::distance(containter.begin(), i))。-这是一个更“通用”的解决方案,并且由于专业化,在随机访问迭代器情况下的性能相同,但否则会产生可怕的性能影响

但是,我不会推荐其中任何一个,因为它会混淆代码(并且可能性能不佳)。相反,正如其他人所说,使用额外的计数器。在需要时使用索引并没有什么“错误”,而是更喜欢迭代器旨在帮助编写“通用”代码,因为这样您就可以将算法应用于不同的容器或容器的子集,等等

于 2010-06-12T18:41:29.397 回答
1

对于某些迭代器类型,只需从初始迭代器中减去当前迭代器:

index = it - levels.begin()

由于这不适用于 std::list 迭代器,因此只需使用变量显式跟踪索引,如上述答案中所述。使用迭代器和容器的好处并没有丢失。您正在添加容器不提供的要求。

于 2010-06-12T18:40:16.107 回答
0

你必须写一些类似的东西

size_t index = 0;
for (list<...>::const_iterator it = y.begin(); it != y.end(); ++it) {
   // Do your actions based on `index`
   ++index;
}

而且,嗯,这有时是合适的。

另一方面,您可以重构(重新规划)您的应用程序,以便您的实际绘图循环不必制作所有这些x += something, y += something2, ...,而是​​按以下方式执行:

foreach (Level* level, list) {
    level->draw(backend);
}

有时可能会很棘手,但在我看来,如果您的应用程序变得“大”,这种方法可以为您节省大量时间。

于 2010-06-12T18:24:31.740 回答
0

您可以但只能用于随机访问迭代器。如果它是一个随机访问迭代器,您可以从开始迭代器中减去您的迭代器以获得索引(不保留单独的 int 索引变量)。

for (vector<int>::const_iterator cit = v.begin(); cit != v.end(); ++cit)
{
   cout << "This is element no: " << cit - v.begin() << endl;
}

不幸的是,在您的示例中,您将无法做到这一点,因为您使用的是 std::list,它只是一个双向迭代器。使用 std::vector ,你可以像我的例子那样做。

于 2010-06-12T18:39:18.043 回答