Topic: Iterators and deletion..
Author: Niklas_Pson@nosmam.hotmail.com (Niklas Pettersson)
Date: Tue, 17 Jul 2001 22:44:30 GMT Raw View
Hello again!
Just wanted to include some real code instead of my pseudo C++ in my last
mail.. The question is the same, is this allowed??
(My real problem is that I have two iterators nested on the same container
and the inner is removing objects from the container)
#include <iostream>
#include <list>
int main()
{
typedef std::list<int *> TestListType;
TestListType l;
l.push_back(new int(10));
l.push_back(new int(20));
l.push_back(new int(30));
TestListType::iterator j;
for (j = l.begin(); j != l.end(); j++)
{
int *int_obj = *j;
std::cout << *int_obj << std::endl;
if (*int_obj == 20)
l.remove(int_obj);
}
return (0);
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Ole Reinartz <ole.reinartz@gmx.de>
Date: Wed, 18 Jul 2001 15:16:51 GMT Raw View
Niklas Pettersson wrote:
> Hello again!
>
> Just wanted to include some real code instead of my pseudo C++ in my last
> mail.. The question is the same, is this allowed??
> (My real problem is that I have two iterators nested on the same container
> and the inner is removing objects from the container)
>
> #include <iostream>
> #include <list>
>
> int main()
> {
> typedef std::list<int *> TestListType;
>
> TestListType l;
> l.push_back(new int(10));
> l.push_back(new int(20));
> l.push_back(new int(30));
>
> TestListType::iterator j;
>
> for (j = l.begin(); j != l.end(); j++)
> {
> int *int_obj = *j;
>
> std::cout << *int_obj << std::endl;
>
> if (*int_obj == 20)
> l.remove(int_obj);
> }
>
> return (0);
> }
I read out of an online manual from SGI (dont have the url handy):
"Lists have the important property that insertion and splicing do not
invalidate iterators to list elements, and that even removal invalidates only
the iterators that point to the elements that are removed. "
So in your example case it is not allowed, because you remove the entry j is
pointing to. You could work around that by reseting j to l.begin, or ++j
before you remove (you would have to reorder your loop then).
Did I miss something?
Ole
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Warwick Molloy" <wmolloy@optushome.com.au-nospam>
Date: Wed, 18 Jul 2001 16:42:06 GMT Raw View
Hi Niklas,
An int * is not the same as std::list<int*>::iterator.
Your favourite C++ compiler should really barf on this due to type
mismatch.
Why even do it? Why not just do this instead for your conditional
removal?
if (*(*j) == 20 ) l.remove(j);
Also, don't forget that removing a pointer from the list (as the remove
call performs) does not destroy the memory pointed to by the pointer...
so it should be:
if (*(*j) == 20)
{
delete **j;
l.remove(j);
}
Regards,
Warwick.
<snip>
>
> #include <iostream>
> #include <list>
>
> int main()
> {
> typedef std::list<int *> TestListType;
>
> TestListType l;
> l.push_back(new int(10));
> l.push_back(new int(20));
> l.push_back(new int(30));
>
> TestListType::iterator j;
>
> for (j = l.begin(); j != l.end(); j++) {
> int *int_obj = *j;
>
> std::cout << *int_obj << std::endl;
>
> if (*int_obj == 20)
> l.remove(int_obj);
> }
>
> return (0);
> }
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Ron Natalie <ron@sensor.com>
Date: Wed, 18 Jul 2001 17:17:13 GMT Raw View
Warwick Molloy wrote:
> An int * is not the same as std::list<int*>::iterator.
> Your favourite C++ compiler should really barf on this due to type
> mismatch.
Nothing requires an implementation to use a distinct type for the
iterator, which can allow certain stupidities like interchanging
T* with container<T>::iterator to escape detection.
However, I'm not sure what this has to do with his problem.
He doesn't do anything wrong (even conceptually) with regard
to this. int_obj = *j is perfectly legitimate. *j has type
int*. l.remove() likewise is legitimate, it wants the value
of something in the list (not the iterator as erase would).
It would have probably been more efficient if he had used
erase.
However, the real problem is that the iterator j is invalid
after the element it is "pointing" to is deleted.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Marcin 'Qrczak' Kowalczyk" <qrczak@knm.org.pl>
Date: Wed, 18 Jul 2001 18:27:56 GMT Raw View
Wed, 18 Jul 2001 16:42:06 GMT, Warwick Molloy <wmolloy@optushome.com.au-n=
ospam> pisze:
> if (*(*j) =3D=3D 20)
> {
> delete **j;
> l.remove(j);
> }
You meant
delete *j;
l.remove(j)
and it's still illegal: it leaves in the list an object (namely the
pointer) accessing which is undefined behavior (because it's deleted).
You should store the pointer somewhere, remove the node from the list,
and then delete the pointer.
--=20
__("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/
\__/
^^ SYGNATURA ZAST=CAPCZA
QRCZAK
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]