web-dev-qa-db-fra.com

Puis-je incrémenter un itérateur en ajoutant simplement un nombre?

Puis-je faire des calculs normaux avec des itérateurs, c'est-à-dire simplement l'incrémenter en ajoutant un nombre?

Par exemple, si je veux supprimer l'élément vec[3], je peux juste faire ceci:

std::vector<int> vec;
for(int i = 0; i < 5; ++i){
      vec.Push_back(i);
}
vec.erase(vec.begin() + 3); // removes vec[3] element

Cela fonctionne pour moi (g ++), mais je ne sais pas si c'est garanti pour fonctionner.

43
Frank

Cela fonctionne si l'itérateur est un itérateur à accès aléatoire, quels sont les itérateurs du vecteur (voir référence ). La fonction STL std::advance peut être utilisé pour faire avancer un itérateur générique, mais comme il ne renvoie pas l'itérateur, j'ai tendance à utiliser + s'il est disponible car il a l'air plus propre.

Note C++ 11

Maintenant, il y a std::next et std::prev , qui faire retourne l'itérateur, donc si vous travaillez dans un pays modèle, vous pouvez les utiliser pour faire avancer un itérateur générique et avoir toujours du code propre.

48
Todd Gardner

Un point subtil est que le operator+ prend un Distance; c'est-à-dire un entier signé. Si vous incrémentez l'itérateur d'un signe non signé, vous risquez de perdre en précision et de vous surprendre. Par exemple sur un système 64 bits,

std::size_t n = (1 << 64) - 2;
std::vector<double> vec(1 << 64);
std::vector<double> slice(vec.begin() + n, vec.end());

conduit à un comportement défini par l'implémentation. Avec g++ ou clang, vous pouvez demander au compilateur de vous avertir de ces conversions indésirables avec l'indicateur d'avertissement -Wsign-conversion qui ne fait pas partie du canonique -Wall ou -Wextra.

Une solution consiste à travailler directement sur le pointeur

std::vector<double> slice(vec.data() + n, vec.data() + vec.size());

Ce n'est pas joli mais correct. Dans certains cas, vous devez construire l'itérateur manuellement, par exemple

std::vector<double>::iterator fromHere{vec.data() + n};
vec.erase(fromHere, vec.end());
2
Fred Schoen

Il fonctionne avec des itérateurs à accès aléatoire. En général, vous voudrez peut-être regarder std :: advance qui est plus générique. Assurez-vous simplement de comprendre les implications sur les performances de l'utilisation de ce modèle de fonction.

2
Nemanja Trifunovic