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

BSc*_*ker 16 c++ stl linked-list

我目前有以下for循环:

for(list<string>::iterator jt=it->begin(); jt!=it->end()-1; jt++)
Run Code Online (Sandbox Code Playgroud)

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

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

我相信STL列表是一个双向链表,所以从我的角度来看,应该可以做到这一点.

建议吗?提前致谢

Den*_*ose 8

使用标准库的必要建议:

std::for_each(lst.begin(), --lst.end(), process);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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


Nas*_*zta 6

List迭代器不是随机迭代器.您应该执行以下操作:

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

还有一件事:++jt反对使用jt++.jt++源代码通常看起来像这样:

iterator operator++ (int i)
{
  iterator temp = (*this);
  ++(*this);
  return temp;
}; 
Run Code Online (Sandbox Code Playgroud)


小智 6

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

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

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

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

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