Supposons que j'ai une carte stl où les valeurs sont des pointeurs et que je veux les supprimer tous. Comment devrais-je représenter le code suivant, mais utiliser STD :: for_each? Je suis heureux que des solutions utilisent Boost. (J'ai trouvé Boost's (également, aux fins de cette question, ignorez le fait que stocker des pointeurs bruts qui nécessitent la suppression dans un conteneur STL ISN 'T très sensible). P> coché_delete code>, mais je ne sais pas comment appliquer cela au
paire
4 Réponses :
Vous devez faire un objet de fonction:
std::vector<int*> v; v.push_back(new int); throw "leaks!"; // nothing in vector is deleted wrapped_container<std::vector<int*> > v; v.container.push_back(new int); throw "no leaks!"; // wrapped_container destructs, deletes elements
Je pensais que cela pourrait être quelque chose comme ça. J'avais espéré qu'il serait possible de le faire sans définir mon propre type. Est-il possible d'utiliser Boost :: Bind ou Select2nd ou Somesuch, je me demande?
Cela n'invoque-t-il pas techniquement ub si la carte décide de se réélanger et commence ainsi à copier des pointeurs supprimés? Peut-être aussi les nulles aussi? - Je viens de remarquer que c'est un hash_map pas une carte, il n'y a donc pas de rééquilibrer
@JK: Cela ne supprime rien de la carte, supprimant simplement des objets qu'il pointe.
@JK: Pourquoi une carte définirait-elle au hasard des pointeurs sur la carte pour NULL? Ce serait une carte terriblement brisée.
ce ne serait peut-être peut-être que vous devriez les nuler après les avoir supprimées
@JK: Il n'y a pas de but à annuler après avoir supprimé. Ce n'est pas fait jusqu'à ce que la carte soit hors de portée. Les pointeurs nullables après la suppression sont mon habitude numéro un détesté. :]
L'OP n'a pas dit que c'était juste avant que le conteneur lui-même soit détruit. Si quelque chose d'autre arrive que le conteneur copie de l'une de ses éléments internes, il copiera un pointeur supprimé, techniquement ub IIRC. nuller les pointeurs les rendra en sécurité pour copier à nouveau.
@JK: assez juste. C'est assez inuré de maintenir un conteneur après avoir tout supprimé. Un Clear () code> devrait être en magasin après les supprimer tous. Si vous gardez un pointeur autour de celui que vous avez supprimé, vous le faites mal. I> C'est pourquoi il n'y a jamais de raison de définir un pointeur sur NULL après l'avoir supprimé; Une fois que vous l'avez supprimé, ne le conserve pas B>.
Si possible, vous devez utiliser des pointeurs intelligents sur votre carte. P>
L'utilisation de pointeurs intelligents ici supprime la nécessité de refactoriser et de déboguer la suppression des membres. Une gestion de la mémoire moins à craindre d'aller de l'avant. Chaque fois que j'utilise new / Suppr Je pense vraiment que c'est nécessaire. Une "odeur de code" personnelle (par Martin Fowler), si vous aimez. P>
Bien sûr, si votre ancien code renvoie une carte, l'approche FOR_EHACH CODE> est probablement votre meilleur choix - mais si vous avez eu une main dans la création de la carte, je recommanderais d'utiliser des pointeurs intelligents. p>
Cela devrait être possible à un moment donné. Je refactore un peu de code plutôt ancien pour le moment. En vérité, j'étais juste curieux de savoir si je pouvais le faire dans une ligne de code. Mais vous avez absolument raison, finalement, j'aimerais y arriver ... mais cela fait partie d'un million de lignes de code de 15 ans.
Si vous avez besoin d'allouer de manière dynamique des éléments, le concept de propriété partagée ne s'applique pas, vous pouvez jeter un coup d'œil sur boost :: pTR_map code>.
Avez-vous essayé d'utiliser boost_foreach? Cela devrait vous permettre de le faire dans une ligne sans créer votre propre foncteur.
Je n'ai pas testé le code suivant, mais cela devrait ressembler à ceci (sinon exactement): P>
typedef stdext::hash_map<int, Foo *> MyMapType; //see comment. BOOST_FOREACH( MyMapType::value_type& p, myMap ) { delete p.second; }
Généralement sonner. Malheureusement, c'est une macro et ne peut pas gérer des virgules entre <> code>
Ah oui, un typedef serait nécessaire, désolé pour cela, plus une ligne.
OK, j'ai découvert comment le faire dans une ligne ... mais je ne pense pas que je ferais jamais ce qui suit en vrai code!
std::for_each( mayMap.begin() , myMap.end() , boost::bind( &boost::checked_delete<Foo> , boost::bind( &stdext::hash_map<int, Foo *>::value_type::second, _1 ) ) );
Nice utilisation de l'opération PreinCremrement sur votre itérateur!