HOWTO · C++
Comment retirer un élément d'un vecteur en C++
Cet article montre comment retirer un élément d'un vecteur en C++
Sur cette page
Pour supprimer un élément à une position connue ou une plage, appelez std::vector::erase. Pour supprimer tous les éléments égaux à une valeur en C++20, utilisez std::erase ; avec les versions antérieures de C++, combinez std::remove et erase selon l’idiome erase-remove. Les exemples montrent l’effet de chaque méthode sur le vecteur et expliquent comment conserver des itérateurs valides.
Supprimer un élément avec std::vector::erase
std::vector::erase accepte un itérateur désignant un élément ou une plage semi-ouverte [first, last). La plage inclut first et exclut last. La surcharge qui supprime un seul élément exige un itérateur valide pointant vers un élément. Elle renvoie un itérateur vers l’élément qui suit la plage supprimée, ou end() si aucun élément ne suit.
Cet exemple complet supprime l’élément à l’indice 2, puis lit l’itérateur renvoyé :
Exécutez cet exemple :
Le code et les libellés ou sorties affichés dans cette section restent en anglais.
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{10, 20, 30, 40, 50};
auto next = numbers.erase(numbers.begin() + 2);
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << "\nNext value: " << *next << '\n';
}
10 20 40 50
Next value: 40
La suppression invalide les itérateurs et les références situés à la position supprimée ou après celle-ci. Mettez à jour ces références ou cessez de les utiliser avant de vous en servir à nouveau. Pour supprimer une plage, transmettez son premier itérateur et l’itérateur situé juste après son dernier élément ; l’itérateur renvoyé et les règles d’invalidation sont les mêmes. Si la plage supprimée va jusqu’à la fin, l’itérateur renvoyé est égal à numbers.end() et ne peut pas être déréférencé.
Supprimer toutes les valeurs correspondantes avec std::erase (C++20)
C++20 ajoute la surcharge non membre de std::erase pour std::vector, déclarée dans <vector>. Elle supprime tous les éléments égaux à la valeur fournie et renvoie le nombre d’éléments supprimés. Si la valeur apparaît plusieurs fois, toutes ses occurrences sont supprimées : cette méthode convient donc lorsque la sélection repose sur l’égalité. Les versions antérieures de la norme ne proposent pas cette surcharge ; utilisez l’idiome erase-remove présenté dans la section suivante.
Cet exemple utilise std::erase avec C++20 et l’idiome erase-remove avec une version antérieure. Dans les deux cas, toutes les occurrences de 2 sont supprimées et le nombre d’éléments supprimés est affiché :
Le code et les libellés ou sorties affichés dans cette section restent en anglais.
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3, 2, 4, 2, 5};
std::size_t removed;
#if __cplusplus >= 202002L
removed = std::erase(numbers, 2);
#else
const auto old_size = numbers.size();
const auto new_end = std::remove(numbers.begin(), numbers.end(), 2);
numbers.erase(new_end, numbers.end());
removed = old_size - numbers.size();
#endif
std::cout << "Removed: " << removed << "\nRemaining: ";
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << '\n';
}
Removed: 3
Remaining: 1 3 4 5
La surcharge de std::erase pour std::vector est disponible depuis C++20 et renvoie le nombre d’éléments supprimés. Avec une version antérieure de la norme, l’exemple utilise l’idiome erase-remove, expliqué ci-dessous.
Supprimer les valeurs correspondantes avec l’idiome erase-remove
Avant C++20, combinez std::remove, fourni par <algorithm>, avec la méthode membre erase du vecteur. std::remove déplace les valeurs qui ne correspondent pas vers le début de la plage modifiable et renvoie un itérateur vers leur nouvelle fin logique. Cette opération ne modifie pas la taille du vecteur : celui-ci contient toujours son nombre initial d’éléments tant que la plage finale n’a pas été supprimée. Transmettez à erase l’itérateur renvoyé et le end() d’origine du vecteur pour réduire la taille du conteneur.
Cet exemple supprime toutes les occurrences de 2 selon cette méthode en deux étapes :
Le code et les libellés ou sorties affichés dans cette section restent en anglais.
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3, 2, 4, 5};
const auto new_end = std::remove(numbers.begin(), numbers.end(), 2);
numbers.erase(new_end, numbers.end());
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << '\n';
}
La plage transmise à std::remove doit être modifiable, car l’algorithme réorganise les valeurs conservées. Le fait qu’un conteneur fournisse un accès en lecture seule par des itérateurs constants n’empêche pas d’utiliser cet idiome lorsqu’une plage d’itérateurs modifiables est disponible.
Supprimer des éléments en toute sécurité pendant une itération
Lorsqu’un prédicat ou une autre condition détermine les éléments à supprimer, utilisez une boucle avec itérateur. Après une suppression, affectez à l’itérateur celui renvoyé par erase ; incrémentez-le uniquement lorsque l’élément courant est conservé. L’itérateur de l’élément supprimé est invalide : l’incrémenter ou le déréférencer n’est donc pas sûr.
Cet exemple supprime les valeurs paires tout en conservant un itérateur valide :
Le code et les libellés ou sorties affichés dans cette section restent en anglais.
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3, 4, 5, 6, 7};
for (auto it = numbers.begin(); it != numbers.end();) {
if (*it % 2 == 0) {
it = numbers.erase(it);
} else {
++it;
}
}
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << '\n';
}
Utilisez std::erase pour supprimer selon l’égalité en C++20, l’idiome erase-remove pour cette même tâche avec les versions antérieures, et erase dans une boucle qui utilise l’itérateur renvoyé lorsque la suppression dépend d’une condition. Le bon choix dépend du critère de sélection : une position ou une plage connue, l’égalité avec une valeur, ou un prédicat évalué au fil de la boucle.