迭代器列表中的倒数第二个元素

时间:2011-06-21 19:34:06

标签: c++ stl linked-list

我目前有以下for循环:

for(list<string>::iterator jt=it->begin(); jt!=it->end()-1; jt++)

我有一个字符串列表,列在一个更大的列表中(list<list<string> >)。我想循环遍历内部列表的内容,直到我到达倒数第二个元素。这是因为我已经处理了最终元素的内容,没有理由再次处理它们。

但是,使用it->end()-1无效 - 我无法在此处使用-运算符。虽然我可以使用--运算符,但这会在每个循环中减少这个最终迭代器。

我认为STL列表是一个双向链表,所以从我的角度来看,应该可以这样做。

么?提前致谢

5 个答案:

答案 0 :(得分:8)

使用标准库的必要建议:

std::for_each(lst.begin(), --lst.end(), process);

如果您不想为创建一个仿函数[我几乎从不这样做]而烦恼,并且您不能使用反向迭代器,那么将结束检查提升出来:

for(iterator i = lst.begin(), j = --lst.end(); i != j; ++i) {
    // do
    // stuff
}

或者,您可以信任优化器,以确认它不必继续重新创建结束条件,并自行吊装。这有多可靠取决于列表实现,循环代码的复杂程度以及优化程序的优异程度。

无论如何,只要做最容易理解的事情,并在完成后担心性能。

答案 1 :(得分:6)

列表迭代器不是随机迭代器。您应该执行以下操作:

if ( ! it->empty() )
{
  list<string>::iterator test = it->end();
  --test;
  for( list<string>::iterator jt = it->begin(); jt != test; ++jt )
  {
  ...
  }
}

还有一件事:对++jt使用jt++jt++源代码通常如下所示:

iterator operator++ (int i)
{
  iterator temp = (*this);
  ++(*this);
  return temp;
}; 

答案 2 :(得分:4)

  

虽然我可以使用 - 运算符,但这会在每个循环中减少这个最终迭代器。

不,它不会。它将获得结束迭代器的副本并减少它。就这样。它不会更改列表中存储的结束迭代器。

您的主要问题应该是验证列表为空,从而确保--it-&gt; end()存在。

答案 3 :(得分:4)

反向迭代器怎么样?

for(list<string>::reverse_iterator jt=++(it->rbegin()); jt!=it->rend(); jt++)

答案 4 :(得分:4)

在c ++ 11及更高版本中,最佳答案似乎是使用std::prev

for(iterator i = lst.begin(); i != std::prev(lst.end()); ++i) {
    // do
    // stuff
}

http://en.cppreference.com/w/cpp/iterator/prev上std :: prev的文档说明,

  

尽管表达式--c.end()经常编译,但不保证这样做:c.end()是一个右值表达式,并且没有迭代器要求指定rvalue的减量保证工作。特别是,当迭代器实现为指针时, - c.end()不会编译,而std :: prev(c.end())会执行。

我相信空列表中的std :: prev()是未定义的,因此您可能需要将其包装在!i.empty()条件