Je dois parcourir un vecteur de la fin au début. La façon "correcte" est
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit)
{
//do Something
}
Lorsque quelque chose implique de connaître l’indice réel, quelques calculs doivent être effectués avec rit pour l’obtenir, comme index = v.size() - 1 - (rit - v.rbegin)
De toute façon, si l’indice est nécessaire, alors je crois fermement qu’il est préférable d’itérer l’utilisation de cet index
for(int i = v.size() - 1; i >= 0; --i)
{
//do something with v[i] and i;
}
Ceci avertit que i
est signé et que v.size()
est non signé .
for(unsigned i = v.size() - 1; i >= 0; --i)
est juste incorrect du point de vue fonctionnel, car il s'agit essentiellement d'une boucle sans fin :)
Quel est le bon moyen esthétique de faire ce que je veux faire?
J'espère que je ne cherche pas quelque chose qui n'existe pas :)
Comme vous l'avez noté, le problème avec une condition de i >= 0
lorsqu'il n'est pas signé est que la condition est toujours vraie. Au lieu de soustraire 1 lorsque vous initialisez i
, puis à nouveau après chaque itération, soustrayez 1 après avoir vérifié la condition de boucle:
for (unsigned i = v.size(); i-- > 0; )
J'aime ce style pour plusieurs raisons:
i
soit renvoyé à UINT_MAX
à la fin de la boucle, il ne fait pas compter ce comportement - cela fonctionnerait de la même manière si les types étaient signés. Compter sur des enveloppes non signées est un peu comme un piratage pour moi.size()
exactement une fois.>=
. Chaque fois que je vois cet opérateur dans une boucle for
, je dois le relire pour m'assurer qu'il ne s'agit pas d'une erreur off-by-one.Il n'y a rien pour arrêter votre boucle reverse_iterator
en utilisant également l'index, comme décrit dans plusieurs autres réponses. De cette façon, vous pouvez utiliser l'itérateur ou l'index selon vos besoins dans la partie // do the work
, pour un coût supplémentaire minime.
size_t index = v.size() - 1;
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin();
rit != v.rend(); ++rit, --index)
{
// do the work
}
Bien que je sois curieux de savoir pourquoi vous avez besoin de l’index. Accéder à v[index]
équivaut à accéder à *rit
.
être esthétiquement agréable! ;)
for(unsigned i = v.size() - 1; v.size() > i; --i)
Je préférerais la variante d'itérateur inverse, car il est toujours facile à interpréter et permet d'éviter les erreurs liées à l'index.
Parfois, vous pouvez simplement utiliser le BOOST_REVERSE_FOREACH
, ce qui donnerait à votre code l'aspect suivant:
reverse_foreach (int value, vector) {
do_something_with_the_value;
}
En fait, vous pouvez toujours utiliser des instructions foreach
pour ces types de boucles, mais elles deviennent alors un peu non évidentes:
size_t i = 0;
foreach (int value, vector) {
do_something;
++i;
}
Essayez un do pendant que:
std::vector<Type> v;
// Some code
if(v.size() > 0)
{
unsigned int i = v.size() - 1;
do
{
// Your stuff
}
while(i-- > 0);
}
Salut, je pense que la meilleure façon d'utiliser itérateur comme vous utilisez dans le premier échantillon et si vous avez besoin d'obtenir un index d'itérateur vous pouvez utiliser.