Quelqu'un peut-il me dire comment incrémenter l'itérateur de 2?
iter++
est disponible - dois-je faire iter+2
? Comment puis-je atteindre cet objectif?
Cette méthode fonctionnera pour les itérateurs qui ne sont pas des itérateurs à accès aléatoire, mais elle peut toujours être spécialisée par l'implémentation pour ne pas être moins efficace que iter += 2
lorsqu'elle est utilisée avec des itérateurs à accès aléatoire.
http://www.cplusplus.com/reference/std/iterator/advance/
std::advance(it,n);
où n est 2 dans votre cas.
La beauté de cette fonction est que, si "il" est un itérateur à accès aléatoire, le
it += n
l’opération est utilisée (c’est-à-dire le vecteur <,> :: iterator). Sinon, son rendu à
for(int i = 0; i < n; i++)
++it;
(c'est-à-dire la liste <..> :: iterator)
Si vous ne possédez pas la valeur modifiable d'un itérateur ou si vous souhaitez obtenir une copie d'un itérateur donné (sans modifier l'original), C++ 11 est accompagné de nouvelles fonctions d'assistance - std::next
/ std::prev
:
std::next(iter, 2); // returns a copy of iter incremented by 2
std::next(std::begin(v), 2); // returns a copy of begin(v) incremented by 2
std::prev(iter, 2); // returns a copy of iter decremented by 2
Vous pouvez utiliser l'opérateur 'affectation par addition'
iter += 2;
Si vous ne savez pas si vous avez suffisamment d'éléments suivants dans votre conteneur, vous devez vérifier la fin de votre conteneur entre chaque incrément. Ni ++ ni std :: advance ne le feront pour vous.
if( ++iter == collection.end())
... // stop
if( ++iter == collection.end())
... // stop
Vous pouvez même lancer votre propre fonction d'avance liée sécurisée.
Si vous êtes sûr de ne pas dépasser la fin, std :: advance (iter, 2) est la meilleure solution.
Nous pouvons utiliser à la fois avance et suivant. Mais, il y a une différence entre les deux. "advance" modifie son argument et ne renvoie rien. Alors, il peut être utilisé comme:
vector<int> v;
v.Push_back(1);
v.Push_back(2);
auto itr = v.begin();
advance(itr, 1); //modifies the itr
cout << *itr<<endl //prints 2
"next" renvoie une copie modifiée de l'itérateur
vector<int> v;
v.Push_back(1);
v.Push_back(2);
cout << *next(v.begin(), 1) << endl; //prints 2
En supposant que la taille de la liste ne soit pas un multiple de l’étape, vous devez vous prémunir contre le débordement:
static constexpr auto step = 2;
// Guard against invalid initial iterator.
if (!list.empty())
{
for (auto it = list.begin(); /*nothing here*/; std::advance(it, step))
{
// do stuff...
// Guard against advance past end of iterator.
if (std::distance(it, list.end()) > step)
break;
}
}
Selon l'implémentation de la collection, le calcul de la distance peut être très lent. Ci-dessous est optimal et plus lisible. La fermeture pourrait être changée en un modèle d'utilitaire avec la valeur de fin de liste passée par la référence const:
const auto advance = [&](list_type::iterator& it, size_t step)
{
for (size_t i = 0; it != list.end() && i < step; std::next(it), ++i);
};
static constexpr auto step = 2;
for (auto it = list.begin(); it != list.end(); advance(it, step))
{
// do stuff...
}
S'il n'y a pas de boucle:
static constexpr auto step = 2;
auto it = list.begin();
if (step <= list.size())
{
std::advance(it, step);
}