geeksforgeeks - list iterator c++
Iteración sobre un vector en dirección inversa (9)
Como ha notado, el problema con una condición de i >= 0
cuando no está firmado es que la condición siempre es verdadera. En lugar de restar 1 al inicializar i
y luego nuevamente después de cada iteración, reste 1 después de verificar la condición del ciclo:
for (unsigned i = v.size(); i-- > 0; )
Me gusta este estilo por varias razones:
- Aunque
i
UINT_MAX
aUINT_MAX
al final del ciclo, no depende de ese comportamiento; funcionaría igual si los tipos se firmaran. Depender de un envolvente sin firma me parece un poco complicado. - Llama a
size()
exactamente una vez. - No usa
>=
. Cada vez que veo ese operador en un buclefor
, tengo que volver a leerlo para asegurarme de que no haya un error "uno por uno". - Si cambia el espaciado en el condicional, puede hacer que use el operador "goes to" .
Necesito iterar sobre un vector desde el final hasta el principio. La forma "correcta" es
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit)
{
//do Something
}
Cuando doSomething implica conocer el índice real, se deben realizar algunos cálculos con rit para obtenerlo, como index = v.size() - 1 - (rit - v.rbegin)
Si el índice se necesita de todos modos, creo firmemente que es mejor iterar usando ese índice
for(int i = v.size() - 1; i >= 0; --i)
{
//do something with v[i] and i;
}
Esto da una advertencia de que v.size()
firmado y v.size()
no tiene firma. Cambiando a
for(unsigned i = v.size() - 1; i >= 0; --i)
es funcionalmente incorrecto, porque esto es esencialmente un ciclo sin fin :)
¿Cuál es una manera estéticamente buena de hacer lo que quiero hacer que
- está libre de advertencia
- no involucra moldes
- no es excesivamente detallado
Espero no estar buscando algo que no exista :)
Creo que:
for(unsigned i = v.size() - 1; i >= 0; --i)
está bien si revisas
!v.empty()
más temprano.
Hola, creo que es mejor usar iterator como lo utilizas en la primera muestra y si necesitas obtener el índice de iterador puedes usar std :: distance para calcularlo, si entiendo tu pregunta
No hay nada que impida que su bucle reverse_iterator
también use el índice como se describe en muchas otras respuestas. De esta forma, puede usar el iterador o índice según sea necesario en la parte // do the work
, por un costo adicional mínimo.
size_t index = v.size() - 1;
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin();
rit != v.rend(); ++rit, --index)
{
// do the work
}
Aunque tengo curiosidad por saber para qué necesitas el índice. Acceder a v[index]
es lo mismo que acceder a *rit
.
Pruebe hacer mientras:
std::vector<Type> v;
// Some code
if(v.size() > 0)
{
unsigned int i = v.size() - 1;
do
{
// Your stuff
}
while(i-- > 0);
}
condición de bucle i != std::numeric_limits<unsigned>::max()
... o use UINT_MAX
si cree que es verboso. o de otra manera:
for(unsigned j=0, end=v.size(), i=end-1; j<end; --i, ++j)
o
for(unsigned end=v.size(), i=end-1; (end-i)<end; --i)
para ser estéticamente agradable! ;)
for(unsigned i = v.size() - 1; v.size() > i; --i)
Preferiría la variante inversa del iterador, porque aún es fácil de interpretar y permite evitar los errores relacionados con el índice.
A veces, simplemente puede usar BOOST_REVERSE_FOREACH
, lo que haría que su código se vea de la siguiente manera:
reverse_foreach (int value, vector) {
do_something_with_the_value;
}
En realidad, siempre puedes usar declaraciones foreach
para este tipo de bucles, pero luego se vuelven poco evidentes:
size_t i = 0;
foreach (int value, vector) {
do_something;
++i;
}
for (it = v.end()-1; it != v.begin()-1; --it)
{
}
El operador "goes to" definitivamente se mete con la cabeza.