Cleaning up an STL list/vector of pointers - c++

What is the shortest chunk of C++ you can come up with to safely clean up a std::vector or std::list of pointers? (assuming you have to call delete on the pointers?)
list<Foo*> foo_list;
I'd rather not use Boost or wrap my pointers with smart pointers.

For std::list<T*> use:
while(!foo.empty()) delete foo.front(), foo.pop_front();
For std::vector<T*> use:
while(!bar.empty()) delete bar.back(), bar.pop_back();
Not sure why i took front instead of back for std::list above. I guess it's the feeling that it's faster. But actually both are constant time :). Anyway wrap it into a function and have fun:
template<typename Container>
void delete_them(Container& c) { while(!c.empty()) delete c.back(), c.pop_back(); }

Since we are throwing down the gauntlet here... "Shortest chunk of C++"
static bool deleteAll( Foo * theElement ) { delete theElement; return true; }
foo_list . remove_if ( deleteAll );
I think we can trust the folks who came up with STL to have efficient algorithms. Why reinvent the wheel?

for(list<Foo*>::const_iterator it = foo_list.begin(); it != foo_list.end(); ++it)
{
delete *it;
}
foo_list.clear();

If you allow C++11, you can do a very short version of Douglas Leeder's answer:
for(auto &it:foo_list) delete it; foo_list.clear();

It's really dangerous to rely on code outside of the container to delete your pointers. What happens when the container is destroyed due to a thrown exception, for example?
I know you said you don't like boost, but please consider the boost pointer containers.

template< typename T >
struct delete_ptr : public std::unary_function<T,bool>
{
bool operator()(T*pT) const { delete pT; return true; }
};
std::for_each(foo_list.begin(), foo_list.end(), delete_ptr<Foo>());

I'm not sure that the functor approach wins for brevity here.
for( list<Foo*>::iterator i = foo_list.begin(); i != foo_list.end(); ++i )
delete *i;
I'd usually advise against this, though. Wrapping the pointers in smart pointers or using a specialist pointer container is, in general, going to be more robust. There are lots of ways that items can be removed from a list ( various flavours of erase, clear, destruction of the list, assignment via an iterator into the list, etc. ). Can you guarantee to catch them all?

The following hack deletes the pointers when your list goes out of scope using RAII or if you call list::clear().
template <typename T>
class Deleter {
public:
Deleter(T* pointer) : pointer_(pointer) { }
Deleter(const Deleter& deleter) {
Deleter* d = const_cast<Deleter*>(&deleter);
pointer_ = d->pointer_;
d->pointer_ = 0;
}
~Deleter() { delete pointer_; }
T* pointer_;
};
Example:
std::list<Deleter<Foo> > foo_list;
foo_list.push_back(new Foo());
foo_list.clear();

At least for a list, iterating and deleting, then calling clear at the end is a bit inneficient since it involves traversing the list twice, when you really only have to do it once. Here is a little better way:
for (list<Foo*>::iterator i = foo_list.begin(), e = foo_list.end(); i != e; )
{
list<Foo*>::iterator tmp(i++);
delete *tmp;
foo_list.erase(tmp);
}
That said, your compiler may be smart enough to loop combine the two anyways, depending on how list::clear is implemented.

Actually, I believe the STD library provides a direct method of managing memory in the form of the allocator class
You can extend the basic allocator's deallocate() method to automatically delete the members of any container.
I /think/ this is the type of thing it's intended for.

for(list<Foo*>::const_iterator it = foo_list.begin(); it != foo_list.end(); it++)
{
delete *it;
}
foo_list.clear();
There's a small reason why you would not want to do this - you're effectively iterating over the list twice.
std::list<>::clear is linear in complexity; it removes and destroys one element at a time within a loop.
Taking the above into consideration the simplest to read solution in my opinion is:
while(!foo_list.empty())
{
delete foo_list.front();
foo_list.pop_front();
}

Since C++11:
std::vector<Type*> v;
...
std::for_each(v.begin(), v.end(), std::default_delete<Type>());
Or, if you are writing templated code and want to avoid specifying a concrete type:
std::for_each(v.begin(), v.end(),
std::default_delete<std::remove_pointer<decltype(v)::value_type>::type>());
Which (since C++14) can be shortened as:
std::for_each(v.begin(), v.end(),
std::default_delete<std::remove_pointer_t<decltype(v)::value_type>>());

void remove(Foo* foo) { delete foo; }
....
for_each( foo_list.begin(), foo_list.end(), remove );

for (list<Foo*>::const_iterator i = foo_list.begin(), e = foo_list.end(); i != e; ++i)
delete *i;
foo_list.clear();

This seems cleanest imo, but your c++ version must support this type of iteration (I believe anything including or ahead of c++0x will work):
for (Object *i : container) delete i;
container.clear();

Related

Effective clearing of vector memory

Well I am creating a vector like this
vector<Member*> emp;
Then I am creating heap objects of the member class like this
Member* memObj = new Member();
Then using push_back like this
emp.push_back(memObj);
Well after using all my functions do I have to clear the memory by iterating like this ?
for( vector<Member*>::iterator iter = emp.begin();
iter != emp.end(); )
{
Member* mem = *iter;
iter = emp.erase (iter);
delete mem;
//iter++;
}
Is there any effective way other than iterating through each value? clear function calls the destructor only and it clears the values but does not free the memory..I wish to achieve polymorphism here...I am new in C++ ....please help..Thanks in advance.. :) I am not using C++11
If you are able to use a C++11 compiler, you can use one of the smart pointers.
std::unique_ptr
std::vector<std::unique_ptr<Member>> emp;
or
std::shared_ptr
std::vector<std::shared_ptr<Member>> emp;
EDIT
If you are not able to use a C++11 compiler, VS 2005 is definitely too old to support C++11, you will have to delete the objects manually, like you have shown.
However, I would add a helper class to help with deleteing the Member objects.
struct MemberDeleteHelper
{
MemberDeleteHelper(std::vector<Member*> emp) : emp_(emp);
~MemberDeleteHelper()
{
for( vector<Member*>::iterator iter = emp.begin();
iter != emp.end(); ++iter )
{
delete *iter;
}
}
std::vector<Member*>& emp_;
};
and use it as:
vector<Member*> emp;
MemberDeleteHelper deleteHelper(emp);
With this in place, the elements of emp will be deleted no matter how you return from the function. If an exception gets thrown from a nested function call, the stack will be unrolled and the elements of emp will still be deleted.
EDIT 2
Do not use auto_ptr objects in std::vector. The pitfalls of using auto_ptr in STL containers are discussed at http://www.devx.com/tips/Tip/13606 (Thanks are due to #pstrjds for the link).
Unless your intent is to added instances of types derived from Member to the vector, there's no need for vector<Member*>, just use vector<Member>.
If you actually need dynamic allocation, use vector<unique_ptr<Member>>. The smart pointer will automatically delete the instances when you clear() the vector. If this is the case, don't forget that Member needs a virtual destructor.
Similar options for pre-C++11 compilers are std::vector<std::tr1::shared_ptr<Member>> or boost::ptr_vector<Member>.
Finally, your current code has a bug. vector::erase returns a pointer to the next element, so by manually incrementing the iterator within the loop, you're skipping every other element. And I don't understand why you're going through the trouble of storing the pointer in a temporary variable. Your loop should be
for( vector<Member*>::iterator iter = emp.begin(); iter != emp.end(); )
{
delete *iter;
iter = emp.erase(iter);
}
or just delete all the elements first and then clear the vector
for( vector<Member*>::iterator iter = emp.begin(); iter != emp.end(); ++iter)
{
delete *iter;
}
emp.clear();

What is the most concise way to clear a map and delete contents?

I have a std::list and a std::map that I would like to empty and call delete on all the pointers.
After reading this question I am using this for the std::list:
mylist.remove_if([](myThingy* thingy) -> bool { delete thingy; return true; });
Is there something similarly concise for std::map?
Note that I cannot use a range based for loop because it isn't supported by my compiler (VC10). If it would be possible I assume
for(auto* thingy : myMap) { delete thingy; }
myMap.clear();
would work. Please correct me if I am wrong.
Is there something similarly concise for std::map?
You could do it this way (supposing your thingy is the mapped value, and not the key):
for_each(myMap.begin(), myMap.end(),
[] (decltype(myMap)::value_type const& p) { delete p.second; });
myMap.clear();
Concerning the range-based for loop:
If it would be possible I assume
for(auto* thingy : myMap) { delete thingy; }
myMap.clear();
would work. Please correct me if I am wrong.
More or less. You still need to keep in mind that values of a map are actually pairs - but you could fix the range-based for to keep that into account, yes:
for (auto&& p : myMap) { delete p.second; }
myMap.clear();
Anyway, please consider using smart pointers instead of performing manual memory management through raw pointers, new, and delete. This way you would avoid this kind of problems.
I don't think your remove_if solution is a good idea for the
other types, either. Just use a simple loop (or foreach):
for ( auto current = myMap.begin(); current != myMap.end(); ++ current ) {
delete current->second;
}
myMap.clear();
Note that you cannot do a delete current->first; this will
invalidate keys in the map. And unless you are doing
a clear() immediately afterwards (or are destructing the map),
set the deleted pointer to NULL.
With regards to your second question:
for ( auto* thingy : myMap )
would certainly not work. The value type of map is a pair, not
a pointer, so you'ld need somthing like:
for ( auto thingy : myMap ) { delete thingy.second; }
(I think. I've not been able to experiment with this either.)

Is this a valid way of removing items from of std::vector?

Here's my code for updating a list of items in a vector and removing some of them:
std::vector<Particle*> particles;
...
int i = 0;
while ( i < particles.size() ) {
bool shouldRemove = particles[ i ]->update();
if ( shouldRemove ) {
delete particles[ i ];
particles[ i ] = particles.back();
particles.pop_back();
} else {
i++;
}
}
When I find an item that should be removed, I replace it with the last item from the vector to avoid potentially copying the rest of the backing array multiple times. Yes, I know it is premature optimization...
Is this a valid way of removing items from the vector? I get some occasional (!) crashes somewhere around this area but can't track them down precisely (LLDB fails to show me the line), so I would like to make sure this part is OK. Or is it... ?
UPDATE: I found the bug and indeed it was in another part of my code.
Yes, this is a valid way. But if it is not a performance bottleneck in your program then it's better to use smart pointers to manage the lifetime of Particle objects.
Take a look at std::remove_if.
Also, might be good to use a shared pointer as it may make life easier :-)
typedef std::shared_ptr< Particle > ParticlePtr;
auto newend = std::remove_if( particles.begin(), particles.end(), [](ParticlePtr p) {return p->update();} );
particles.erase( newend, particles.end() );
You are iterating over an STL vector, so use iterators, it's what they're for.
std::vector<Particle*>::iterator particle = particles.begin();
while ( particle != particles.end() ) {
bool shouldRemove = particle->update();
if ( shouldRemove ) {
particle = particles.remove(particle); //remove returns the new next particle
} else {
++particle;
}
}
Or, even better, use smart pointers and the erase/remove idiom. Remove_if itself does as you describe, moving old members to the back of the vector and returning an iterator pointing to the first non-valid member. Passing this and the vector's end() to erase allows erase to erase all the old members as they are in a contiguous block. In your scenario, you would have to delete each before calling erase:
auto deleteBegin = std::remove_if(
particles.begin(), particles.end(),
[](Particle* part){ return part->update();}));
for(auto deleteIt = deleteBegin; deleteIt != particles.end(); ++deleteIt)
delete *deleteIt;
std::erase(deleteBegin, particles.end());
Or pre C++11:
bool ShouldDelete(Particle* part) {
return part->update();
}
typedef vector<Particle*> ParticlesPtrVec;
ParticlesPtrVec::iterator deleteBegin = std::remove_if(
particles.begin(), particles.end(), ShouldDelete);
for(ParticlesPtrVec::iterator deleteIt = deleteBegin;
deleteIt != particles.end(); ++deleteIt)
delete *deleteIt;
std::erase(deleteBegin, particles.end());
Then test the whole code for performance and optimise wherever the actual bottlenecks are.
I don't see any direct issue in the code. You are probably having some issues with the actual pointers inside the vector.
Try running valgrind on your code to detect any hidden memory access problems, or switch to smart pointers.

Deleting entries in STL vector

I want to clean up the threads which pointers are stored in STL vector. I am doing it as below. Is this right way of doing as i am deleting entries while looping thourgh vector or there is better way to do this.
Please suggest.
template <typename threadFuncParamT >
bool ThreadPool<threadFuncParamT>::KillSleepingThreads()
{
if(m_vecThreads.size() != 0)
{
for (; std::vector< ThreadWrapper < threadFuncParamT>* >::iterator itrCollThreads != values.end(); )
{
ThreadWrapper < threadFuncParamT> *pWrapper = m_vecThreads.back();
m_vecThreads.pop_back();
delete pWrapper;
} // for loop
} // if condition
}
Thanks!
If you're allowed to use C++11, then make it cute:
for (auto it = m_vecThreads.begin() ; it != m_vecThreads.end(); ++it )
{
delete *it;
}
m_vecThreads.clear();
You can make it even more cute (in C++11, of course - thanks to #celtschk's comment):
for (auto & ptr: m_vecThreads) //it is called range-based for loop
{
delete ptr;
}
m_vecThreads.clear();
Or if you're not allowed to use C++11, then replace auto (in the first for loop) with this:
typename std::vector<ThreadWrapper<threadFuncParamT*>::iterator
//^^^^^^^^ you've to typename as well
Note that you've to use typename as well, for iterator is a dependent name.
Also, the following is not needed, remove it from your code:
if(m_vecThreads.size() != 0) // not needed!
Try this in your function:
for(size_t i = 0; i < m_vecThreads.size(); ++i)
{
delete m_vecThreads[i];
}
m_vecThreads.clear();
It looks a lot more complicated then it needs to. If you are really trying to just delete every item in the vector, just delete each item then clear the entire vector.
for(std::vector<ThreadWrapper<threadFuncParamT*>>::iterator
i = m_vecThreads.begin();
i != m_vecThreads.end();
++i)
{
delete *i;
}
m_vecThreads.clear();
As an aside, it's usually a better practice to have a vector of smart pointers (eg boost::shared_ptr) than having to explicitly delete items.

Vector Iterators Casting

Hey, In C++, I have a vector of type:
vector<BaseClass*> myVector;
In which, I insert (push_back) pointers of derived classes into it.
Now, I want to pop back its elements so I do this:
vector<ADlgcDev*>::iterator iter;
for (iter = myVector.rbegin(); iter != myVector.rend(); iter++)
{
// but before I pop it, I need to shutdown it down
// so I cast this
// but this way, I'm unable to call the function
(DerivedClass*(*iter))->Shutdown();
myVector.pop_back();
}
but as mention in the comments before I pop it, I need to call its Shutdown() method and the cast is not working properly too. Any resolutions? or is impossible?
while (!myVector.empty())
{
((DerivedClass*)(myVector.back()))->Shutdown();
myVector.pop_back();
}
Notes:
You should probably use dynamic_cast instead of the hard cast. (If it's sure that there are only DerivedClass objects in the vector, why isn't it std::vector<DerivedClass>?)
You should probably not have to cast at all, since Shutdown() should be declared in the base class.
You should probably delete the objects, too, before you pop them off the vector. (But that might not be so.)
You should probably use a smart pointer which calls Shutdown() (and delete, probably).
Edit: Using std::vector<T>::clear(), as shown by markh44 is probably better than the pop_back().
Could you make Shutdown a virtual function in BaseClass? Then you wouldn't need a cast.
Also you'll probably have trouble removing items from a vector while iterating. I'd do it like this:
vector<BaseClass*>::iterator iter;
for (iter = myVector.rbegin(); iter != myVector.rend(); iter++)
{
(*iter)->Shutdown();
}
myVector.clear();
Edit: and another thing, ++iter is generally preferred over iter++.
The constructor casting doesn't work for pointers. Use static_cast if you're sure or dynamic_cast and check.
If Shutdown() is a virtual method of the Base class i.e. BaseClass::ShutDown() you should directly call iter->ShutDown();
Otherwise if the method isn't virtual you should use dynamic_cast.
vector<ADlgcDev*>::iterator iter;
for (iter = myVector.rbegin(); iter != myVector.end(); iter++)
{
DerivedClassA* a = dynamic_cast<DerivedClassA*>( *iter ) ;
if ( a ) a->ShutDownA();
else
{
DerivedClassB* b = dynamic_cast<DerivedClassB*>(*iter);
if ( b ) b->ShutDownB();
// ... repeat for every class in hierarchy that might be in the vector.
}
myVector.pop_back();
}
Anyway you're probably leaking memory, unless ShutDown() deletes the object from itself (which is generally a bad idea ) or you're keeping duplicated pointers and deleting them elsewhere, which is another risky idea.