library - libreria list c++
¿Cómo se itera hacia atrás a través de una lista STL? (5)
Estoy escribiendo un código multiplataforma entre Windows y Mac.
Si list :: end () "devuelve un iterador que se dirige a la ubicación que sucede al último elemento de una lista" y se puede verificar al atravesar una lista, ¿cuál es la mejor forma de retroceder?
Este código funciona en Mac pero no en Windows (no puede disminuir más allá del primer elemento):
list<DVFGfxObj*>::iterator iter = m_Objs.end();
for (iter--; iter!=m_Objs.end(); iter--)// By accident discovered that the iterator is circular ?
{
}
esto funciona en Windows:
list<DVFGfxObj*>::iterator iter = m_Objs.end();
do{
iter--;
} while (*iter != *m_Objs.begin());
¿Hay alguna otra manera de atravesar hacia atrás que podría implementarse en un bucle for?
Como ya mencionó Ferruccio, use reverse_iterator:
for (std::list<int>::reverse_iterator i = s.rbegin(); i != s.rend(); ++i)
Esto debería funcionar:
list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for (; iter!= m_Objs.rend(); iter++)
{
}
Probablemente quieras los iteradores inversos. De memoria:
list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for( ; iter != m_Objs.rend(); ++iter)
{
}
Use reverse_iterator en lugar de iterator. Utilice rbegin () y rend () en lugar de begin () y end ().
Otra posibilidad, si te gusta usar la macro BOOST_FOREACH es usar la macro BOOST_REVERSE_FOREACH introducida en Boost 1.36.0.
La mejor / más fácil manera de invertir la iteración de una lista es (como ya se dijo) para usar los iteradores inversos rbegin / rend.
Sin embargo, sí quería mencionar que los iteradores inversos se implementan almacenando la posición del iterador "actual" de a una (al menos en la implementación de GNU de la biblioteca estándar).
Esto se hace para simplificar la implementación, para que el rango en reversa tenga la misma semántica que un rango hacia adelante [inicio, fin] y [reiniciar, desgarrar]
Lo que esto significa es que desreferenciar un iterador implica crear un nuevo temporal, y luego disminuirlo, todas y cada una de las veces :
reference
operator*() const
{
_Iterator __tmp = current;
return *--__tmp;
}
Por lo tanto, desreferenciar un reverse_iterator es más lento que un iterador normal.
Sin embargo, en su lugar puede usar los iteradores bidireccionales regulares para simular la iteración inversa usted mismo, evitando esta sobrecarga:
for ( iterator current = end() ; current != begin() ; /* Do nothing */ )
{
--current; // Unfortunately, you now need this here
/* Do work */
cout << *current << endl;
}
Las pruebas mostraron que esta solución es ~ 5 veces más rápida para cada desreferencia utilizada en el cuerpo del bucle.
Nota: Las pruebas no se realizaron con el código anterior, ya que std :: cout habría sido el cuello de botella.
También Nota: la diferencia de ''reloj de pared'' fue ~ 5 segundos con un tamaño de lista estándar de 10 millones de elementos. Entonces, de manera realista, a menos que el tamaño de tus datos sea tan grande, solo mantente en rbegin () rend ()!