Sign in to follow this  

deleting the contents of a std::map

This topic is 4359 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello! Nice xmas theme..... I have a puzzle over the best way to delete the contents of a std::map, in MSVC2003 Using a std::vector, I normally iterate thru the vector, SAFE_DELETEing, then do a .clear(); I tried this: std::map< int, cProxyObject*, std::less<int> >::iterator iter; for ( iter = m_objectList.begin(); iter != m_objectList.end(); ++iter ) delete *iter; m_objectList.clear(); but it doesnt like the delete *iter; line. Any suggestions gratefully appreciated! Si

Share this post


Link to post
Share on other sites
Following up on this subject, I have now come across a further problem. Here's my code:

for ( iter = m_objectList.begin(); iter != m_objectList.end(); ++iter )
{
SAFE_DELETE( iter->second );
//m_objectList.erase( iter );
g_log->Log( L"%d objects remaining\n", m_objectList.size() );
}

This is a puzzle. The code successfully deletes all the objects stored in iter->second, but the m_objectList still contains NULLed entries.

Okay, so by uncommenting the above line, the m_objectList.size() reflects only the undeleted objects. Seems greats but......

Unfortunately, by using .erase() I seem to be mucking up the iterator loop. How can I loop though something which I am deleting!!!

I tried:
m_objectList.erase( iter->first );
but same results.

Thanks in advance

Simon

Share this post


Link to post
Share on other sites
Quote:
Original post by sipickles
Unfortunately, by using .erase() I seem to be mucking up the iterator loop. How can I loop though something which I am deleting!!!


This just came up here, but it was for a list, so for a map, it's still the same logics [wink]

iter = m_objectList.begin();
while(iter != m_objectList.end())
{
SAFE_DELETE( iter->second );
m_objectList.erase( iter );
g_log->Log( L"%d objects remaining\n", m_objectList.size() );
iter = m_objectList.begin();
}

That's it! Of course if you look further down the page on that last link, SiCrane suggests just calling clear at the end rather than try to delete as you go - which is the best thing to do, unless you are not erasing all the tiems in the map. For example, you would want to use my code if you had:


iter = m_objectList.begin();
while(iter != m_objectList.end())
{
SAFE_DELETE( iter->second );
m_objectList.erase( iter );
g_log->Log( L"%d objects remaining\n", m_objectList.size() );
if(objectList.size() % 2 == 0)
break;
iter = m_objectList.begin();
}

In which case, you definitly don't want to call clear at the end. [wink]

Share this post


Link to post
Share on other sites
If you are going to erase as you go you might as well do:

while (!m_objectList.empty())
{
SAFE_DELETE(m_objectList->begin()->second);
m_objectList.erase(m_objectList.begin());
g_log->Log( L"%d objects remaining\n", m_objectList.size() );
}


As Drew says above, it would probably be faster to delete them and then clear at the end. I haven't looked at how they code clear() but hopefully it isn't by iteratoring through each one and deleting them one at a time (while relinking everything)

Share this post


Link to post
Share on other sites
But what if you only want to delete some of them?

[edit - add code for delete_if_we_should. :P]



bool delete_if_we_should(iterator I)
{
if (some_test_involving_I)
{
delete I->second;
return true;
}
return false;
}

for (iterator I = container.begin(); I != container.end(); )
{
if (delete_if_we_should(I)) I = container.erase(I);
else ++I;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Deyja
But what if you only want to delete some of them?


for (iterator I = container.begin(); I != container.end(); )
{
if (delete_if_we_should(I)) I = container.erase(I);
else ++I;
}


In a map, erase doesn't return an iterator.


for (iterator I = container.begin(); I != container.end(); )
{
if (delete_if_we_should(I))
{
iterator nextI = I; nextI++;
container.erase(I);
I = nextI;
}
else ++I;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by nprz
In a map, erase doesn't return an iterator.


for (iterator I = container.begin(); I != container.end(); )
{
if (delete_if_we_should(I))
{
iterator nextI = I; nextI++;
container.erase(I);
I = nextI;
}
else ++I;
}


Alternatively:


for (iterator I = container.begin(); I != container.end(); )
{
if (delete_if_we_should(I))
container.erase(I++);
else
++I;
}


Since the post-increment operator on an iterator returns a copy of the original (pre-incremented) iterator, this is fine.. erase() will erase the element identified by that copy, and the original is incremented. (this is also why one should avoid using I++ if ++I is all that is needed)

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Quote:
Original post by SiCrane
Of course you can save yourself some headaches by using a map of smart pointers or possibly boost::ptr_map.


You see this post? These are some of the headaches you could have saved.


Headaches??? opportunities.... surely?!!

Share this post


Link to post
Share on other sites

This topic is 4359 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this