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
Mary-Kate Olsenoriginal
2024-12-04 08:30:14596parcourir

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

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

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!

Déclaration:
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