Maison > développement back-end > C++ > La suppression d'éléments d'un « std::set » pendant l'itération est-elle un comportement défini en C ou spécifique à l'implémentation ?

La suppression d'éléments d'un « std::set » pendant l'itération est-elle un comportement défini en C ou spécifique à l'implémentation ?

Mary-Kate Olsen
Libérer: 2024-12-04 08:30:14
original
630 Les gens l'ont consulté

Is Deleting Elements from a `std::set` During Iteration Defined Behavior in C   or Implementation-Specific?

Supprimer des éléments de std::set pendant l'itération : implications de mise en œuvre

Itérer dans un ensemble tout en supprimant des éléments peut présenter des défis, car l'opération pourrait potentiellement invalider l'itérateur. Dans ce contexte, la question se pose : ce comportement est-il défini par le standard C ou est-il spécifique à l'implémentation ?

Dépendance d'implémentation

Selon le standard C (23.1 .2.8), l'insertion d'éléments dans un ensemble ne doit pas affecter les itérateurs ou les références au conteneur, tandis que l'effacement d'éléments ne doit qu'invalider les itérateurs et les références au conteneur. éléments supprimés. Cependant, le comportement des itérateurs lors des opérations d'effacement n'est pas explicitement spécifié, ce qui le laisse ouvert à des décisions spécifiques à l'implémentation.

Implémentation de GCC

Dans l'exemple de code fourni, en utilisant GCC 4.3.3 sur Ubuntu 10.04, l'effacement d'éléments d'un ensemble pendant l'itération n'invalidait pas l'itérateur. Cela suggère que la mise en œuvre de GCC suit une approche plus détendue, permettant l'utilisation continue de l'itérateur après l'effacement.

Solution conforme

Pour garantir la conformité à la norme, une approche différente est requis. Une solution courante consiste à créer une copie de l'itérateur avant d'effacer l'élément :

for (auto it = numbers.begin(); it != numbers.end(); ) {
    if (*it % 2 == 0) {
        numbers.erase(it++);
    }
    else {
        ++it;
    }
}
Copier après la connexion

Dans ce cas, l'incrément postfix (it ) transmet l'ancienne position à la fonction delete() tout en sautant simultanément à l'itérateur. élément suivant. L'incrément de suffixe est préféré ici car il évite le problème potentiel de double incrément qui peut survenir avec l'incrément de préfixe (lorsque la condition est fausse).

Mise à jour C 11

Avec Avec l'avènement du C 11, une solution plus élégante est disponible. La fonction effacer() renvoie désormais un itérateur vers l'élément qui suit le dernier élément supprimé (ou set::end si le dernier élément a été supprimé). Cela permet une mise en œuvre plus concise :

for (auto it = numbers.begin(); it != numbers.end(); ) {
    if (*it % 2 == 0) {
        it = numbers.erase(it);
    }
    else {
        ++it;
    }
}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal