delete des elements d'un map
Le
JBB
Bonjour à tous,
voilà mon problème:
j'ai une map de pointeurs
std::map<CLEF,OBJECT * > ma_map;
quand j'ai besoin de la vider avant le clear() je fais:
std::map<CLEF,OBJECT * >::iterator it = ma_map.begin();
while (ma_map.end()!= it) {
delete (it++)->second;
}
je me demande si il est possible de faire ça en une seule ligne?
(car j'ai plain de map de ce type a vider )
pour l'instant j'ai plusieurs pistes:
1) créer un classe mapPointeur<CLEF,OBJECT> : public map<CLEF,OBJECT *>
qui définirait une methode deleteall()
je ferais ainsi ma_map.deleteall()
2) me créer une fonction template
template <class MAP> void deleteall(MAP & map){
MAP::iterator
}
je ferais ainsi deleteall(ma_map)
3) trouver le truc qui existe déjà tout fait dans la Stl
genre std::deleteall(ma_map.begin(),ma_map.end())
Vos avis sur la question.
(rq le même problème se pose avec n'importe quel container)
voilà mon problème:
j'ai une map de pointeurs
std::map<CLEF,OBJECT * > ma_map;
quand j'ai besoin de la vider avant le clear() je fais:
std::map<CLEF,OBJECT * >::iterator it = ma_map.begin();
while (ma_map.end()!= it) {
delete (it++)->second;
}
je me demande si il est possible de faire ça en une seule ligne?
(car j'ai plain de map de ce type a vider )
pour l'instant j'ai plusieurs pistes:
1) créer un classe mapPointeur<CLEF,OBJECT> : public map<CLEF,OBJECT *>
qui définirait une methode deleteall()
je ferais ainsi ma_map.deleteall()
2) me créer une fonction template
template <class MAP> void deleteall(MAP & map){
MAP::iterator
}
je ferais ainsi deleteall(ma_map)
3) trouver le truc qui existe déjà tout fait dans la Stl
genre std::deleteall(ma_map.begin(),ma_map.end())
Vos avis sur la question.
(rq le même problème se pose avec n'importe quel container)

Poser une question


Et ne pourrais-tu pas faire une map de pointeurs
intelligents ?
void clear_prt_map( std::map<CLEF,OBJECT * >& m){
for( std::map m.end()!= it ; it++) {
delete (it)->second;
}
Sauf qu'à la connaissance, les conteneurs de la STL ne sont
pas fait pour être hérité (pb de destructeur et de virtualité).
Oui
Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)
Techniquement, c'est un comportement indéfini, bien que dans la
pratique, je ne peux pas imaginer que ça pose de problème.
Alors, une fonction ?
template< typename Key, typename Value >
void
mapDeleter( std::map< Key, Value >& m )
{
for ( std::map i != m.end() ;
++ i ) {
Value p = i->second ;
i->second = NULL ;
delete p ;
}
m.clear() ;
}
Deux autres possibilités :
-- Ce que je préfère :
template< typename Key, typename Value >
void
mapDeleter( std::map< Key, Value >& m )
{
while ( ! m.empty() ) {
Value p = begin()->second ;
m.erase( begin() ) ;
delete p ;
}
}
A l'avantage qu'à aucun instant le map ne contient des
pointeurs null.
-- Sans le clear intégré :
template< typename M >
struct MapDeleter
{
void operator()( M::value_type& obj ) const
{
M::mapped_type tmp = obj.second ;
obj.second = NULL ;
delete tmp ;
}
} ;
template< typename M >
MapDeleter< M >
makeDeleter( M& )
{
return MapDeleter< M >() ;
}
puis :
std::for_each( m.begin(), m.end(), makeDeleter( m ) ) ;
Pas forcément une bonne idée. Les collections de la norme ne
sont pas conçues pour l'héritage.
C'est à peu près ce que je ferais aussi, voir ci-dessus.
Peut-être dans boost, mais pas dans la bibliothèque standard.
D'abord, pourquoi pas map< CLE, OBJECT >, pour que le problème
n'existe pas. C'est quand même la solution que j'utilise la
plupart du temps.
Et il y a aussi l'option des pointeurs intélligents, dont le
destructeur ferait le delete (et le destructeur du pointeur,
s'il en a, sera appelé par clear()). Dans le cas où le map
serait vraiment résponable de la durée de vie des objets, mais
qu'on ne peut pas en faire membre par valeurs. (C'est un cas qui
se présente assez rarement, à mon avis.)
--
James Kanze (Gabi Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34