473,396 Members | 1,918 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Need help regarding std::list

Ok, in my program I have a std::list<Document*>, where Document is one of my
own classes.

I need to go through this list and check each item if it's ready for
deletion. If it's not, skip to next, if it's ready I take steps to delete
it. The thing is that the list is part of a gui application and the system
removes the Document* from the list during the execution of the loop body.
That means I cant use iterators to iterate over the list. So I tried using
the size of the list, like this:

while(m_documents.size())
{
Document* ptr = m_documents.front();

if(ptr->ready_for_deletion())
{
ptr->clean_up(); // This removes ptr from the list before next
iteration
}
}

The problem with that solution is that I get an endless loop for Documents
not ready for deletion. I need to determine if I've asked a document if it's
ready for deletion or not and loop until all documents have been deleted or
there are only non-ready documents left in the list. I can't think of a
solution. I could create a new list of only Documents ready for deletion and
then delete those, but that's not really an option because when I find a
document ready for deletion, I need to delete it right now, not a bit later.

Not sure I'm making much sense and maybe I'm off-topic. If so, I apologise.

/ WP
Jul 22 '05 #1
11 2232
William Payne wrote:
Ok, in my program I have a std::list<Document*>, where Document is one of my
own classes.

I need to go through this list and check each item if it's ready for
deletion. If it's not, skip to next, if it's ready I take steps to delete
it. The thing is that the list is part of a gui application and the system
removes the Document* from the list during the execution of the loop body.
That means I cant use iterators to iterate over the list.
Yes, you can.

for (std::list<Document*>::iterator it = doclist.begin();
it != doclist.end();
) // note: no ++it
{
Document *pd = *it;
if (pd->ready_for_deletion())
{
pd->clean_up();
delete pd;
it = doclist.erase(it);
}
else
++it;
}

RTFM.
[...]


Victor
Jul 22 '05 #2

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:l6****************@newsread1.dllstx09.us.to.v erio.net...
William Payne wrote:
Ok, in my program I have a std::list<Document*>, where Document is one of
my own classes.

I need to go through this list and check each item if it's ready for
deletion. If it's not, skip to next, if it's ready I take steps to delete
it. The thing is that the list is part of a gui application and the
system removes the Document* from the list during the execution of the
loop body. That means I cant use iterators to iterate over the list.


Yes, you can.

for (std::list<Document*>::iterator it = doclist.begin();
it != doclist.end();
) // note: no ++it
{
Document *pd = *it;
if (pd->ready_for_deletion())
{
pd->clean_up();
delete pd;
it = doclist.erase(it);
}
else
++it;
}

RTFM.
[...]


Victor


Thanks for quick reply, Victor. Interesting solution. Unfortunately, the
actual delete ptr_document; is called somewhere else (working under the
constrains of gui library), but I will see what I can do with your solution.

/ WP
Jul 22 '05 #3
William Payne wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:l6****************@newsread1.dllstx09.us.to.v erio.net...
William Payne wrote:
Ok, in my program I have a std::list<Document*>, where Document is one of
my own classes.

I need to go through this list and check each item if it's ready for
deletion. If it's not, skip to next, if it's ready I take steps to delete
it. The thing is that the list is part of a gui application and the
system removes the Document* from the list during the execution of the
loop body. That means I cant use iterators to iterate over the list.


Yes, you can.

for (std::list<Document*>::iterator it = doclist.begin();
it != doclist.end();
) // note: no ++it
{
Document *pd = *it;
if (pd->ready_for_deletion())
{
pd->clean_up();
delete pd;
it = doclist.erase(it);
}
else
++it;
}

RTFM.

[...]


Victor

Thanks for quick reply, Victor. Interesting solution. Unfortunately, the
actual delete ptr_document; is called somewhere else (working under the
constrains of gui library), but I will see what I can do with your solution.


You can always extract the elements of the list to be deleted into
a separate list and then pass it somewhere else to be disposed of.

Victor
Jul 22 '05 #4

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:IQ***************@newsread1.dllstx09.us.to.ve rio.net...
William Payne wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:l6****************@newsread1.dllstx09.us.to.v erio.net...
William Payne wrote:

Ok, in my program I have a std::list<Document*>, where Document is one
of my own classes.

I need to go through this list and check each item if it's ready for
deletion. If it's not, skip to next, if it's ready I take steps to
delete it. The thing is that the list is part of a gui application and
the system removes the Document* from the list during the execution of
the loop body. That means I cant use iterators to iterate over the list.

Yes, you can.

for (std::list<Document*>::iterator it = doclist.begin();
it != doclist.end();
) // note: no ++it
{
Document *pd = *it;
if (pd->ready_for_deletion())
{
pd->clean_up();
delete pd;
it = doclist.erase(it);
}
else
++it;
}

RTFM.
[...]

Victor

Thanks for quick reply, Victor. Interesting solution. Unfortunately, the
actual delete ptr_document; is called somewhere else (working under the
constrains of gui library), but I will see what I can do with your
solution.


You can always extract the elements of the list to be deleted into
a separate list and then pass it somewhere else to be disposed of.

Victor


Well, say I have this loop (modified yours):
for(list<Document*>::iterator itr = m_documents.begin();
itr != m_documents.end();
) // Note: No ++itr;
{
Document* doc = *itr;

++itr;

if(doc->ready_for_deletion())
{
doc->clean_up(); /* triggers a removal of doc from list elsewhere
*/
}
}

Is itr still valid if doc->clean_up() triggers the system to remove doc from
the list before the next iteration begins?

Right now I wish I could do delete this; in the document class, heh.

/ WP
Jul 22 '05 #5
Victor Bazarov wrote:

[snipp]

for (std::list<Document*>::iterator it = doclist.begin();
it != doclist.end();
) // note: no ++it

for(std::list<Document*>::iterator it = doclist.begin(),
std::list<Docuemnt*>::iterator end_mark = doclist.end();
it != end_mark)

Only for performance reason :-)

SCNR && best regards
Nicolas
Jul 22 '05 #6
William Payne wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:IQ***************@newsread1.dllstx09.us.to.ve rio.net...
William Payne wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:l6****************@newsread1.dllstx09.us.t o.verio.net...
William Payne wrote:
>Ok, in my program I have a std::list<Document*>, where Document is one
>of my own classes.
>
>I need to go through this list and check each item if it's ready for
>deletion. If it's not, skip to next, if it's ready I take steps to
>delete it. The thing is that the list is part of a gui application and
>the system removes the Document* from the list during the execution of
>the loop body. That means I cant use iterators to iterate over the list.

Yes, you can.

for (std::list<Document*>::iterator it = doclist.begin();
it != doclist.end();
) // note: no ++it
{
Document *pd = *it;
if (pd->ready_for_deletion())
{
pd->clean_up();
delete pd;
it = doclist.erase(it);
}
else
++it;
}

RTFM.

>[...]

Victor
Thanks for quick reply, Victor. Interesting solution. Unfortunately, the
actual delete ptr_document; is called somewhere else (working under the
constrains of gui library), but I will see what I can do with your
solution.
You can always extract the elements of the list to be deleted into
a separate list and then pass it somewhere else to be disposed of.

Victor

Well, say I have this loop (modified yours):
for(list<Document*>::iterator itr = m_documents.begin();
itr != m_documents.end();
) // Note: No ++itr;
{
Document* doc = *itr;

++itr;


You can combine them:

Document* doc = *itr++;

but that's not the point.

if(doc->ready_for_deletion())
{
doc->clean_up(); /* triggers a removal of doc from list elsewhere
*/
This is not right IMO. Removal of the document pointer from the list
should be done by him who owns the list. Since you use 'm_documents'
as the variable name, it seems that (*this) object owns the list of
documents and should be deleting the elements from the list. That is
why I suggested 'erase' here.
}
}

Is itr still valid if doc->clean_up() triggers the system to remove doc from
the list before the next iteration begins?
I still think that

for (...
;)
{
Document* pdoc = *itr;
if (pdoc->ready_for_deletion())
{
Do_whatever_cleanup_needed_elsewhere(); // pd is still
// in the list

// now extract the document from the list
itr = m_documents.erase();

Do_whatever_needed_to_dispose_of_(pdoc); // pd is not in
// the list anymore
}
else
++itr; // move to the next one
}

is _cleaner_ and easier to understand. Besides, there is a potential
bad situation. Imagine that you're working on the last element of the
list. When you do

Document *pdoc = *itr++;

'itr' now has the value of 'm_documents.end()', right? Now, let's
suppose that the last document is ready to be removed. The call to

doc->clean_up();

"triggers a removal". Suddenly, the list is shorter by one and its
end() is not where it was when you just did *itr++. You want to compare
the value of 'itr' to m_documents.end(), but it's not the same any more.
You get undefined behaviour because 'itr' doesn't necessarily have the
same value that 'end()' returns. That's why you _really_ need to erase
the element from the list _right_here_, in the same loop (or at least
get the "current end of the list" from your 'clean_up' function). What
is worse is if your 'clean_up' is in a different thread and it _really_
just "triggers" the removal, but doesn't complete it by the time it
returns the control to the caller (to your loop). That's why I also
suggested a simple extraction into a separate list and then removal of
those document in a different function or after this loop or wherever.
Right now I wish I could do delete this; in the document class, heh.


You can only do that if you are sure that no instances of Document are
created in any other way but by 'new'. It's not difficult to do, just
define a factory method in 'Document' class and always call it when you
need to instantiate a Document.

Victor
Jul 22 '05 #7
Nicolas Pavlidis wrote:
Victor Bazarov wrote:

[snipp]

for (std::list<Document*>::iterator it = doclist.begin();
it != doclist.end();
) // note: no ++it


for(std::list<Document*>::iterator it = doclist.begin(),
std::list<Docuemnt*>::iterator end_mark = doclist.end();
it != end_mark)

Only for performance reason :-)


That assumes that the list doesn't change length during the loop
execution, which is _specifically_ *not* the case in the original
post. Please pay attention.

V
Jul 22 '05 #8

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:Ew****************@newsread1.dllstx09.us.to.v erio.net...
William Payne wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:IQ***************@newsread1.dllstx09.us.to.ve rio.net...
William Payne wrote:

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:l6****************@newsread1.dllstx09.us. to.verio.net...
>William Payne wrote:
>
>
>>Ok, in my program I have a std::list<Document*>, where Document is one
>>of my own classes.
>>
>>I need to go through this list and check each item if it's ready for
>>deletion. If it's not, skip to next, if it's ready I take steps to
>>delete it. The thing is that the list is part of a gui application and
>>the system removes the Document* from the list during the execution of
>>the loop body. That means I cant use iterators to iterate over the
>>list.
>
>Yes, you can.
>
> for (std::list<Document*>::iterator it = doclist.begin();
> it != doclist.end();
> ) // note: no ++it
> {
> Document *pd = *it;
> if (pd->ready_for_deletion())
> {
> pd->clean_up();
> delete pd;
> it = doclist.erase(it);
> }
> else
> ++it;
> }
>
>RTFM.
>
>
>
>>[...]
>
>Victor
Thanks for quick reply, Victor. Interesting solution. Unfortunately, the
actual delete ptr_document; is called somewhere else (working under the
constrains of gui library), but I will see what I can do with your
solution.

You can always extract the elements of the list to be deleted into
a separate list and then pass it somewhere else to be disposed of.

Victor

Well, say I have this loop (modified yours):
for(list<Document*>::iterator itr = m_documents.begin();
itr != m_documents.end();
) // Note: No ++itr;
{
Document* doc = *itr;

++itr;


You can combine them:

Document* doc = *itr++;

but that's not the point.

if(doc->ready_for_deletion())
{
doc->clean_up(); /* triggers a removal of doc from list
elsewhere */


This is not right IMO. Removal of the document pointer from the list
should be done by him who owns the list. Since you use 'm_documents'
as the variable name, it seems that (*this) object owns the list of
documents and should be deleting the elements from the list. That is
why I suggested 'erase' here.
}
}

Is itr still valid if doc->clean_up() triggers the system to remove doc
from the list before the next iteration begins?


I still think that

for (...
;)
{
Document* pdoc = *itr;
if (pdoc->ready_for_deletion())
{
Do_whatever_cleanup_needed_elsewhere(); // pd is still
// in the list

// now extract the document from the list
itr = m_documents.erase();

Do_whatever_needed_to_dispose_of_(pdoc); // pd is not in
// the list anymore
}
else
++itr; // move to the next one
}

is _cleaner_ and easier to understand. Besides, there is a potential
bad situation. Imagine that you're working on the last element of the
list. When you do

Document *pdoc = *itr++;

'itr' now has the value of 'm_documents.end()', right? Now, let's
suppose that the last document is ready to be removed. The call to

doc->clean_up();

"triggers a removal". Suddenly, the list is shorter by one and its
end() is not where it was when you just did *itr++. You want to compare
the value of 'itr' to m_documents.end(), but it's not the same any more.
You get undefined behaviour because 'itr' doesn't necessarily have the
same value that 'end()' returns. That's why you _really_ need to erase
the element from the list _right_here_, in the same loop (or at least
get the "current end of the list" from your 'clean_up' function). What
is worse is if your 'clean_up' is in a different thread and it _really_
just "triggers" the removal, but doesn't complete it by the time it
returns the control to the caller (to your loop). That's why I also
suggested a simple extraction into a separate list and then removal of
those document in a different function or after this loop or wherever.
Right now I wish I could do delete this; in the document class, heh.


You can only do that if you are sure that no instances of Document are
created in any other way but by 'new'. It's not difficult to do, just
define a factory method in 'Document' class and always call it when you
need to instantiate a Document.

Victor


Thanks for your reply, Victor. I guess I need to develop a new strategy to
solve this problem. The class that owns the list contains a callback
function that is called by the system, which complicates the matter.

/ WP
Jul 22 '05 #9
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:sz****************@newsread1.dllstx09.us.to.v erio.net...
Nicolas Pavlidis wrote:
Victor Bazarov wrote:

[snipp]

for (std::list<Document*>::iterator it = doclist.begin();
it != doclist.end();
) // note: no ++it


for(std::list<Document*>::iterator it = doclist.begin(),
std::list<Docuemnt*>::iterator end_mark = doclist.end();
it != end_mark)

Only for performance reason :-)


That assumes that the list doesn't change length during the loop
execution, which is _specifically_ *not* the case in the original
post. Please pay attention.


Doesn't the iterator returned by std::list::end() remain valid even if
elements are removed or added from the list (say, via calls to erase() or
insert())? The list's iterators aren't supposed to be invalidated unless
the element to which the iterator is pointing has been removed. Is end() a
special case?

--
David Hilsee
Jul 22 '05 #10
David Hilsee wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:sz****************@newsread1.dllstx09.us.to.v erio.net...
Nicolas Pavlidis wrote:
Victor Bazarov wrote:

[snipp]
for (std::list<Document*>::iterator it = doclist.begin();
it != doclist.end();
) // note: no ++it

for(std::list<Document*>::iterator it = doclist.begin(),
std::list<Docuemnt*>::iterator end_mark = doclist.end();
it != end_mark)

Only for performance reason :-)


That assumes that the list doesn't change length during the loop
execution, which is _specifically_ *not* the case in the original
post. Please pay attention.

Doesn't the iterator returned by std::list::end() remain valid even if
elements are removed or added from the list (say, via calls to erase() or
insert())? The list's iterators aren't supposed to be invalidated unless
the element to which the iterator is pointing has been removed. Is end() a
special case?


I don't know. I try always be on the safer side of things, so when I
am not sure, I'd rather not rely on some behaviour. For example, what
happens to 'end()' if you remove the last element?

V
Jul 22 '05 #11
On Tue, 14 Sep 2004 20:12:01 -0400, "David Hilsee"
<da*************@yahoo.com> wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:sz****************@newsread1.dllstx09.us.to. verio.net...
Nicolas Pavlidis wrote:
> Victor Bazarov wrote:
>
> [snipp]
>
>>
>> for (std::list<Document*>::iterator it = doclist.begin();
>> it != doclist.end();
>> ) // note: no ++it
>
> for(std::list<Document*>::iterator it = doclist.begin(),
> std::list<Docuemnt*>::iterator end_mark = doclist.end();
> it != end_mark)
>
> Only for performance reason :-)


That assumes that the list doesn't change length during the loop
execution, which is _specifically_ *not* the case in the original
post. Please pay attention.


Doesn't the iterator returned by std::list::end() remain valid even if
elements are removed or added from the list (say, via calls to erase() or
insert())? The list's iterators aren't supposed to be invalidated unless
the element to which the iterator is pointing has been removed. Is end() a
special case?


No. As you say, list::end() is never invalidated (unless the list
itself is destroyed).

Tom
Jul 22 '05 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Mike Pemberton | last post by:
I'm sure there's a good explanation for this effect, but I get rather a strange output from this little test: #include <iostream> #include <list> int main() { std::list<int> int_list;
8
by: JustSomeGuy | last post by:
I need to write an new class derived from the list class. This class stores data in the list to the disk if an object that is added to the list is over 1K in size. What methods of the std stl...
5
by: Eric Lilja | last post by:
Hello, consider this complete program (sorry, it's not minimal but I hope it's readable at least): #include <algorithm> #include <iostream> #include <vector> class Row { public:
3
by: Jef Driesen | last post by:
The number of items in my std::list is changed after sorting (using std::list member function sort). I'm using MSVC6 and the actual (pseudo) code is posted below. The output from size() is...
8
by: Spoon | last post by:
Hello, Could someone explain why the following code is illegal? (I'm trying to use a list of (C-style) arrays.) #include <list> typedef std::list < int foo_t; int main() { int v = { 12, 34...
0
by: Javier | last post by:
Hi all, I have this code: class A { std::list<Bm_observadores; void function() {
3
by: Ray D. | last post by:
Hey all, I'm trying to pass a list into a function to edit it but when I compile using g++ I continue to get the following error: maintainNeighbors.cpp:104: error: invalid initialization of...
12
by: isliguezze | last post by:
template <class T> class List { public: List(); List(const List&); List(int, const T&); void push_back(const T &); void push_front(const T &); void pop_back();
17
by: Isliguezze | last post by:
Does anybody know how to make a wrapper for that iterator? Here's my wrapper class for std::list: template <class Tclass List { private: std::list<T*lst; public: List() { lst = new...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.