Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

delete des elements d'un map

2 réponses
Avatar
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)

2 réponses

Avatar
Marc Boyer
Le 13-04-2007, JBB a écrit :
Bonjour à tous,

voilà mon problème:
j'ai une map de pointeurs

std::map<CLEF,OBJECT * > ma_map;


Et ne pourrais-tu pas faire une map de pointeurs
intelligents ?

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 )


void clear_prt_map( std::map<CLEF,OBJECT * >& m){
for( std::map<CLEF,OBJECT * >::iterator it = m.begin();
m.end()!= it ; it++) {
delete (it)->second;
}

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()


Sauf qu'à la connaissance, les conteneurs de la STL ne sont
pas fait pour être hérité (pb de destructeur et de virtualité).

2) me créer une fonction template
template <class MAP> void deleteall(MAP & map){
MAP::iterator ...
}


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)

Avatar
James Kanze
On Apr 13, 12:00 pm, JBB wrote:

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;
}


Techniquement, c'est un comportement indéfini, bien que dans la
pratique, je ne peux pas imaginer que ça pose de problème.

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 )


Alors, une fonction ?

template< typename Key, typename Value >
void
mapDeleter( std::map< Key, Value >& m )
{
for ( std::map< Key, Value >::iterator i = m.begin() ;
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 ) ) ;

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()


Pas forcément une bonne idée. Les collections de la norme ne
sont pas conçues pour l'héritage.

2) me créer une fonction template
template <class MAP> void deleteall(MAP & map){
MAP::iterator ...
}

je ferais ainsi deleteall(ma_map)


C'est à peu près ce que je ferais aussi, voir ci-dessus.

3) trouver le truc qui existe déjà tout fait dans la Stl ...
genre std::deleteall(ma_map.begin(),ma_map.end())


Peut-être dans boost, mais pas dans la bibliothèque standard.

Vos avis sur la question.


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