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)
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.
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
On Apr 13, 12:00 pm, JBB <nos...@nospam.com> 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.
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: james.kanze@gmail.com
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
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.
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