Replacing items in a list using a C++ std::list iterator

DylanTheWebb picture DylanTheWebb · Jun 18, 2013 · Viewed 9.8k times · Source

The basic structure of my code is:

using namespace std;
void recursiveFunction(list <int> &jobs,...){
list<int>::iterator i;
int ii;
//code missing
    for(i=jobs.begin(); i != jobs.end(); ++i){
        //more code missing
        list<int>::iterator tempi(i);
        ii=*i;
        jobs.erase(tempi);
        recursiveFunction(jobs,...);
        jobs.insert(i,ii);
    }
}

As I have discovered, any pointer pointing to a position that is erased is invalidated, so i is invalidated. Is there some way to reinsert the job numbers in this way? Without the performance hit of creating a new list each recursion?

Is there a way to use something other than a list iterator, perhaps?

Answer

Arne Mertz picture Arne Mertz · Jun 18, 2013

list::erase returns an iterator to the element past the (last) erased element, and since list::insert will insert before the element whose iterator you pass it, that's perfect for your needs:

using namespace std;
void recursiveFunction(list <int> &jobs,...){
  //...
  for(auto i = begin(jobs); i != end(jobs);){ 
    //...
    auto tmpElem = *i;
    i = jobs.erase(i);
    recursiveFunction(jobs,...);
    jobs.insert(i,tmpElem);
  }
}

Notes:

  • with i=jobs.erase(i) you effectively increment i. So leave the increment in the for loop. Alternatively use i=jobs.insert(i,tmpElem) later, so i points to the same element again
  • Declare variables (e.g. i, tmpElem) as local as possible, as a matter of good style and maintainability
  • Give variables meaningful names

Depending on what the function does there might be other possibilities to achieve what you want. This way you will work on each subset of list elements, and on many of those multiple times. Consider the list to have the content {1,2,3}, heres' what is going to happen (in pseudo-code):

recursiveFunction({1,2,3},...)
  for-loop, i = &1
    erase(1)
    recursiveFunction({2,3},...)
      for-loop, i = &2
        erase(2)
        recursiveFunction({3},...)    //a
        insert(2)
      //...
    insert(1)
  for-looop, i = &2
    erase(2)
    recursiveFunction({1,3},...)
      for-loop, i = &1
        erase(1)
        recursiveFunction({3},...)    //b
        insert(1)
      //...
    insert(2)
  //...

Lines a and b look the same, although the additional parameters might not be the same - I can't tell from your code. So just keep it in mind and consider if this is what you actually want.