问题
I have a lot of code where I am deleting vector containers that have pointers in them, that is, I have to delete all the pointers first and then clear the container. Every time I would iterate through and delete the pointers manually (I am aware of stl::algorithms for_each). To circumvent all that code, I created a template for deleting all vector containers that have a pointer. So far so good.
Now I have several more container types including maps, concurrent containers etc. all with the same functionality in the end as far as deletion goes. The DeleteContainer(std::vector<T*>& VecIn) function that I have can only work on vectors as mentioned above. Is there any way to make it generic enough to work on all containers?
EDIT: Thanks for all the answers, I wish I could select more than one. To anybody who stumbles onto this question, read all the answers and not just the selected one as they all provide great info.
回答1:
You already have a valid answer, but just to provide an alternative, I believe you should consider using Boost Pointer Container and let it handle memory management :
This library therefore provides standard-like containers that are for storing heap-allocated or cloned objects (or in case of a map, the mapped object must be a heap-allocated or cloned object). For each of the standard containers there is a pointer container equivalent that takes ownership of the objects in an exception safe manner.
回答2:
You could use boost pointer containers.
They hold maintain and delete pointers correctly.
http://www.boost.org/doc/libs/1_38_0/libs/ptr_container/doc/reference.html
{
boost::ptr_vector<int> data;
data.push_back(new int(2));
data.push_back(new int(2));
data.push_back(new int(2));
}
// container deleted and all pointers correctly destroyed.
回答3:
I'll second many people and avise using shared_ptr or boost pointer containers. However, you can write
template <typename Iter>
void delete_pointers(Iter begin, Iter end)
{
for (; begin != end; ++begin) delete *begin;
}
Usage:
std::vector<Foo*> v;
// Initialize Foo objects
delete_pointers(v.rbegin(), v.rend());
I use rbegin and rend instead of begin and end because sometimes, people want objects to be deleted in the reverse order they were created.
You can also do
void destroyFoo(Foo* x) { delete x; }
std::for_each(v.rbegin(), v.rend(), &destroyFoo);
or use C++0x lambdas.
回答4:
You can just use boost::shared_ptr<T> insted of T* and there will not be reason of DeleteContainer. But If you don't want to do this, you can make something like this
template<class T>
void DeleteContainer(typename T::iterator begin, typename T::iterator end)
{
for(;begin!=end;++begin)
delete *begin;
}
then you can just call it for any stl container you want in this way:
std::some_container<int*> s;
DeleteContainer<std::some_container<int*> > (s.begin(), s.end());
回答5:
As suggested by Tomek, we can have a similar solution to handle the deletion. A struct would have been better than a free function.
struct Delete
{
public:
template<typename T>
void operator()(const T* ptr) const
{
delete ptr;
}
void operator()(const char* ptr) const
{
delete[] ptr;
}
};
for_each(some_container.begin(), some_container.end(), Delete());
回答6:
An alternative is to give up on deleting things entirely and commit to using a garbage collector :) You can try the Boehm-Reiser-Detlefs collector, it is standard on Linux (libgc) and it is used in many complex programs now (such as gcc). It's also a good idea to give up on RAII: it was a nice idea at the time but it doesn't work so well in practice. Many resources are independently created and destroyed out of order with their representation.
回答7:
My take on this would be:
template<class T>
void Destroy(T *p)
{
delete p;
}
template<template<typename, typename> class C, typename T1, typename T2>
void Destroy(C<T1 *, T2> &c)
{
std::for_each(c.begin(), c.end(), Destroy<T1>);
}
Tested on g++ 4.4.4 with vector, deque and list. You may need additional overloads of void Destroy(C<T1 *, T2> &c) for other containers and/or other STL implementations.
来源:https://stackoverflow.com/questions/4479381/delete-any-container-using-templates