Удалить любой контейнер с помощью шаблонов
У меня много кода, где я удаляю векторные контейнеры, в которых есть указатели, то есть сначала я должен удалить все указатели, а затем очистить контейнер. Каждый раз, когда я перебираю и удаляю указатели вручную (мне известны stl:: алгоритмы for_each). Чтобы обойти весь этот код, я создал шаблон для удаления всех векторных контейнеров, имеющих указатель. Все идет нормально.
Теперь у меня есть еще несколько типов контейнеров, включая карты, параллельные контейнеры и т. Д., И все они имеют одинаковую функциональность в конце процесса удаления. DeleteContainer(std::vector<T*>& VecIn)
Функция, которая у меня есть, может работать только с векторами, как указано выше. Есть ли способ сделать его достаточно универсальным для работы со всеми контейнерами?
РЕДАКТИРОВАТЬ: Спасибо за все ответы, я хотел бы выбрать более одного. Любой, кто сталкивается с этим вопросом, прочитает все ответы, а не только выбранный, поскольку все они предоставляют отличную информацию.
7 ответов
У вас уже есть действительный ответ, но просто для того, чтобы предоставить альтернативу, я думаю, вам следует рассмотреть возможность использования Boost Pointer Container и позволить ему управлять памятью:
Поэтому эта библиотека предоставляет стандартные контейнеры, предназначенные для хранения выделенных в куче или клонированных объектов (или в случае карты сопоставленный объект должен быть выделенным в куче или клонированным объектом). Для каждого из стандартных контейнеров существует эквивалентный контейнер-указатель, который принимает собственность на объекты безопасным образом.
Вы могли бы использовать контейнеры указателя наддува.
Они держат, поддерживают и удаляют указатели правильно.
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.
Я буду вторым много людей и использовать Avise shared_ptr
или повысить указатель контейнеров. Тем не менее, вы можете написать
template <typename Iter>
void delete_pointers(Iter begin, Iter end)
{
for (; begin != end; ++begin) delete *begin;
}
Использование:
std::vector<Foo*> v;
// Initialize Foo objects
delete_pointers(v.rbegin(), v.rend());
я использую rbegin
а также rend
вместо begin
а также end
потому что иногда люди хотят, чтобы объекты были удалены в обратном порядке их создания.
Вы также можете сделать
void destroyFoo(Foo* x) { delete x; }
std::for_each(v.rbegin(), v.rend(), &destroyFoo);
или используйте лямбды C++0x.
Вы можете просто использовать boost::shared_ptr<T>
поставленный T*
и не будет причины DeleteContainer
, Но если вы не хотите делать это, вы можете сделать что-то вроде этого
template<class T>
void DeleteContainer(typename T::iterator begin, typename T::iterator end)
{
for(;begin!=end;++begin)
delete *begin;
}
тогда вы можете просто вызвать его для любого контейнера stl, который вы хотите следующим образом:
std::some_container<int*> s;
DeleteContainer<std::some_container<int*> > (s.begin(), s.end());
Как предположил Томек, у нас может быть подобное решение для удаления. Структура была бы лучше, чем свободная функция.
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 ());
Мой взгляд на это будет:
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>);
}
Проверено на g++ 4.4.4 с вектором, deque и списком. Вам могут понадобиться дополнительные перегрузки void Destroy (C
Альтернатива - отказаться от полного удаления и использовать сборщик мусора:). Вы можете попробовать сборщик Boehm-Reiser-Detlefs, он является стандартным для Linux (libgc) и сейчас используется во многих сложных программах (таких как: НКА). Это также хорошая идея отказаться от RAII: это была хорошая идея в то время, но она не так хорошо работает на практике. Многие ресурсы создаются и уничтожаются независимо друг от друга с их представлением.