Deleting from std::list

M

Martin Magnusson

I know a similar question was recently posted here, but after trying the
solutions in that thread I still have problems.

list<int> the_list;
the_list.push_back(1);
the_list.push_back(2);
the_list.push_back(3);
the_list.push_back(4);
list<int>::iterator i = the_list.end();
i--;
cout << the_list.size();
for (std::list<int>::iterator j = i;
j != the_list.end();
++j)
{
cout << ".";
j = the_list.erase( j );
}
cout << the_list.size();

What happens is this: j goes to the end of the list and erases the last
element. By then I would have thought that j would be set to nodes.end()
and the loop would terminate, but instead it seems that the loop keeps
running, erasing all of the list. The output of the above code is
"4....0". What am I doing wrong?
 
V

Victor Bazarov

Martin Magnusson said:
I know a similar question was recently posted here, but after trying the
solutions in that thread I still have problems.

list<int> the_list;
the_list.push_back(1);
the_list.push_back(2);
the_list.push_back(3);
the_list.push_back(4);
list<int>::iterator i = the_list.end();
i--;
cout << the_list.size();
for (std::list<int>::iterator j = i;
j != the_list.end();
++j)

What's the purpose of ++j here?
{
cout << ".";
j = the_list.erase( j );
}
cout << the_list.size();

What happens is this: j goes to the end of the list and erases the last
element. By then I would have thought that j would be set to nodes.end()
and the loop would terminate, but instead it seems that the loop keeps
running, erasing all of the list. The output of the above code is
"4....0". What am I doing wrong?

Why are you increasing 'j'? Once 'j' is set to the_list.end(),
using ++ for it causes undefined behaviour. If an iterator is
"one past the end", it is not dereferenceable, which is a pre-
condition for ++.

Victor
 
M

Mike Wahler

Martin Magnusson said:
I know a similar question was recently posted here, but after trying the
solutions in that thread I still have problems.

list<int> the_list;
the_list.push_back(1);
the_list.push_back(2);
the_list.push_back(3);
the_list.push_back(4);
list<int>::iterator i = the_list.end();
i--;
cout << the_list.size();
for (std::list<int>::iterator j = i;

So now 'j' points to the last element (with value of 4.)
j != the_list.end();
++j)
{
cout << ".";
j = the_list.erase( j );

Now 'j' == the_list.end()
We go back to the top of the loop, where 'j' is incremented.
(past end()). Heaven knows what the 'value' of 'j' is now,
but it's not equal to 'end()'. So the body of the loop
executes again. :)

I think we have undefined behavior here.

}
cout << the_list.size();

What happens is this: j goes to the end of the list and erases the last
element. By then I would have thought that j would be set to nodes.end()
and the loop would terminate, but instead it seems that the loop keeps
running, erasing all of the list. The output of the above code is
"4....0". What am I doing wrong?


Try:

for (std::list<int>::iterator j = i;
j != the_list.end();
j = the_list.erase(j))
{
cout << ".";
}

or

for (std::list<int>::iterator j = i;
j != the_list.end();
/* no iteration expression */ )
{
cout << ".";
j = the_list.erase(j);
}

Your '++j' was overwriting the return from erase that
you stored in 'j'.

I must admit it did take me a few minutes to realize
what was going on. :)

HTH,
-Mike
 
J

John Harrison

Martin Magnusson said:
I know a similar question was recently posted here, but after trying the
solutions in that thread I still have problems.

list<int> the_list;
the_list.push_back(1);
the_list.push_back(2);
the_list.push_back(3);
the_list.push_back(4);
list<int>::iterator i = the_list.end();
i--;
cout << the_list.size();
for (std::list<int>::iterator j = i;
j != the_list.end();
++j)
{
cout << ".";
j = the_list.erase( j );
}
cout << the_list.size();

What happens is this: j goes to the end of the list and erases the last
element. By then I would have thought that j would be set to nodes.end()
and the loop would terminate, but instead it seems that the loop keeps
running, erasing all of the list. The output of the above code is
"4....0". What am I doing wrong?

But that isn't the solution that was posted recently. If you really tried
the solution posted recently you would have more luck.

Your problem is that j is set to nodes.end(), but what is the next thing you
do? ++j of course!

This is the correct solution.

for (std::list<int>::iterator j = i;
j != the_list.end();
)
{
cout << ".";
j = the_list.erase( j );
}

Note that ++j has disappeared.

john
 
M

Martin Magnusson

Thanks for your answers, all of you! I wasn't aware that the ++j was
executed before the comparison j!=the_list.end().
 
S

Stuart Golodetz

Martin Magnusson said:
Thanks for your answers, all of you! I wasn't aware that the ++j was
executed before the comparison j!=the_list.end().

A couple more things:

1)

If you really just want to remove the last element of a list, you're better
off just writing:

the_list.pop_back();

2)

Regarding for loops, if you have something like this:

for(int i=0; i<3; ++i)
{
std::cout << i << ' ';
}

What actually happens is something like this (using an "infinite" while
loop, to make things clear):

int i = 0;
while(1)
{
if(!(i < 3)) break;
std::cout << i << ' ';
++i;
}

Hope that clarifies things a bit?

Cheers,

Stuart.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top