开发者

Iterator for second to last element in a list

开发者 https://www.devze.com 2023-03-14 07:12 出处:网络
I currently have the following for loop: for(list<string>::iterator jt=it->begin(); jt!=it->end()-1; jt++)

I currently have the following for loop:

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

I have a list of strings which is in a larger list (list<list<string> >). I want to loop through the contents of the innerlist until I get to the 2nd to last element. This is because I have already processed the contents of the final element, and h开发者_开发技巧ave no reason to process them again.

However, using it->end()-1 is invalid -- I cannot use the - operator here. While I could use the -- operator, this would decrement this final iterator on each cycle.

I believe a STL list is a doubly linked list, so from my perspective, it should be possible to do this.

Advice? Thanks in advance


Requisite recommendation to use the standard library:

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

If you don't want to hassle with creating a functor [I almost never do], and you can't use reverse iterators, hoist the end check out of the loop:

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

Or, you can just trust the optimizer to recognize that it doesn't have to keep recreating the end condition, and do the hoisting itself. How reliable this is depends on the list implementation, and how complex your loop code is, and how good your optimizer is.

At any rate, just do what is easiest for you to understand, and worry about performance after you're done.


List iterator is not random iterator. You should do the following:

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

One more thing: use ++jt against jt++. jt++ source code usually looks something like this:

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


In c++11 and later, the best answer appears to be to use std::prev

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

The documentation for std::prev on http://en.cppreference.com/w/cpp/iterator/prev says,

Although the expression --c.end() often compiles, it is not guaranteed to do so: c.end() is an rvalue expression, and there is no iterator requirement that specifies that decrement of an rvalue is guaranteed to work. In particular, when iterators are implemented as pointers, --c.end() does not compile, while std::prev(c.end()) does.

I believe std::prev() on an empty list is undefined, so you may need to wrap this in a !i.empty() condition


While I could use the -- operator, this would decrement this final iterator on each cycle.

No, it would not. It would get a copy of the end iterator and decrement it. That's all. It would not change the end iterator stored in the list.

Your main issue should be verifying that the list is not empty, thus ensuring that --it->end() exists.


what about a reverse iterator?

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

精彩评论

暂无评论...
验证码 换一张
取 消