Czyszczenie listy STL / wektora wskaźników
Jaki jest najkrótszy fragment C++, jaki można wymyślić, aby bezpiecznie wyczyścić wektor lub listę wskaźników? (zakładając, że musisz wywołać delete na wskaźnikach?)
list<Foo*> foo_list;
Wolałbym nie używać Boost lub owinąć moje wskaźniki Z Inteligentnych wskaźników.
15 answers
Ponieważ rzucamy rękawicę tutaj... "Najkrótszy fragment C++"
static bool deleteAll( Foo * theElement ) { delete theElement; return true; }
foo_list . remove_if ( deleteAll );
Myślę, że możemy zaufać ludziom, którzy wymyślili STL, że mają skuteczne algorytmy. Po co odkrywać koło na nowo?Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-21 00:06:05
Dla std::list<T*>
Zastosowanie:
while(!foo.empty()) delete foo.front(), foo.pop_front();
Dla std::vector<T*>
Zastosowanie:
while(!bar.empty()) delete bar.back(), bar.pop_back();
Nie wiem dlaczego wziąłem front
zamiast back
ZA std::list
powyżej. Myślę, że to uczucie, że jest szybsze. Ale w rzeczywistości oba są stałym czasem :). W każdym razie zawiń go w funkcję i baw się dobrze:
template<typename Container>
void delete_them(Container& c) { while(!c.empty()) delete c.back(), c.pop_back(); }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-16 20:46:11
for(list<Foo*>::const_iterator it = foo_list.begin(); it != foo_list.end(); ++it)
{
delete *it;
}
foo_list.clear();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-16 14:19:38
Jeśli pozwolisz C++11, możesz zrobić bardzo krótką wersję odpowiedzi Douglasa Leedera:
for(auto &it:foo_list) delete it; foo_list.clear();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-12 22:04:31
To naprawdę niebezpieczne polegać na kodzie poza kontenerem, aby usunąć swoje wskaźniki. Co się stanie, gdy kontener zostanie zniszczony na przykład w wyniku wyrzucenia wyjątku?
Wiem, że mówiłeś, że nie lubisz boost, ale proszę rozważ Boost pointer containers.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-20 23:14:26
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>());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 11:30:30
Nie jestem pewien, czy podejście functora wygrywa tutaj za zwięzłość.
for( list<Foo*>::iterator i = foo_list.begin(); i != foo_list.end(); ++i )
delete *i;
Zazwyczaj odradzam to. Owijanie wskaźników w inteligentne wskaźniki lub używanie specjalistycznego kontenera wskaźników jest ogólnie bardziej wytrzymałe. Istnieje wiele sposobów na usunięcie pozycji z listy ( różne smaki erase
, clear
, zniszczenie listy, przypisanie przez iterator do listy itp. ). Możesz zagwarantować, że złapiesz ich wszystkich?Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-20 22:30:26
Poniższy hack usuwa wskaźniki, Gdy twoja lista wychodzi poza zakres używając RAII lub wywołując 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_;
};
Przykład:
std::list<Deleter<Foo> > foo_list;
foo_list.push_back(new Foo());
foo_list.clear();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-14 16:38:16
Przynajmniej w przypadku listy, iteracji i usuwania, a następnie wywołanie clear na końcu jest trochę nieefektywne, ponieważ polega na dwukrotnym przejechaniu listy, podczas gdy naprawdę musisz to zrobić tylko raz. Tutaj jest trochę lepszy sposób:
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);
}
To powiedziawszy, Twój kompilator może być wystarczająco inteligentny, aby loop combine the two anyway, w zależności od sposobu implementacji list:: clear.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-20 23:19:01
Uważam, że biblioteka STD zapewnia bezpośrednią metodę zarządzania pamięcią w postaci klasy alokatora
Można rozszerzyć podstawową metodę alokatora deallocate (), aby automatycznie usuwać elementy dowolnego kontenera.
I / think / this is the type of thing it ' s intended for.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-05 03:55:48
for(list<Foo*>::const_iterator it = foo_list.begin(); it != foo_list.end(); it++)
{
delete *it;
}
foo_list.clear();
Jest mały powód, dla którego nie chcesz tego robić - skutecznie powtarzasz listę dwa razy.
Std::list:: clear jest liniowy w złożoności; usuwa i niszczy jeden element na raz w pętli.
Biorąc pod uwagę powyższe najprostsze do odczytania rozwiązanie moim zdaniem to:
while(!foo_list.empty())
{
delete foo_list.front();
foo_list.pop_front();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-10 06:32:46
Od C++11:
std::vector<Type*> v;
...
std::for_each(v.begin(), v.end(), std::default_delete<Type>());
Lub, jeśli piszesz kod szablonowy i chcesz uniknąć podania konkretnego typu:
std::for_each(v.begin(), v.end(),
std::default_delete<std::remove_pointer<decltype(v)::value_type>::type>());
Które (od C++14) można skrócić jako:
std::for_each(v.begin(), v.end(),
std::default_delete<std::remove_pointer_t<decltype(v)::value_type>>());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-16 11:30:16
void remove(Foo* foo) { delete foo; }
....
for_each( foo_list.begin(), foo_list.end(), remove );
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-05 17:20:12
for (list<Foo*>::const_iterator i = foo_list.begin(), e = foo_list.end(); i != e; ++i)
delete *i;
foo_list.clear();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-20 22:30:30
To wydaje się najczystsze imo, ale twoja wersja c++ musi obsługiwać tego typu iterację (wierzę, że wszystko, co zawiera lub wyprzedza c++0x, zadziała):
for (Object *i : container) delete i;
container.clear();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-02 18:53:04