Pregunta

Al iterar sobre elementos de un vector, se prefiere usar iteradores en lugar de un índice (consulte ¿Por qué usar iteradores en lugar de índices de matriz? ).

std::vector<T> vec;
std::vector<T>::iterator it;
for ( it = vec.begin(); it != vec.end(); ++it )
{
   // do work
}

Sin embargo, puede ser necesario usar el índice en el cuerpo del bucle. ¿Cuál de los siguientes sería preferible en ese caso, considerando el rendimiento y la flexibilidad / extensibilidad?

  1. Volver al bucle indexado
    std::vector vec;
    size_t i;
    for ( i = 0; i < vec.size(); ++i )
    {
       // use i
    }
    
  2. Calcular desplazamiento
    std::vector vec;
    std::vector::iterator it;
    for ( it = vec.begin(); it != vec.end(); ++it )
    {
       size_t i = it - vec.begin(); 
       // use i
    }
    
  3. Usa std :: distance
    std::vector vec;
    std::vector::iterator it;
    for ( it = vec.begin(); it != vec.end(); ++it )
    {
       size_t i = std::distance( vec.begin(), it );
       // use i
    }
    
¿Fue útil?

Solución

Si está planeando utilizar exclusivamente un vector, es posible que desee volver al bucle indexado, ya que transmite su intención más claramente que el bucle de iterador. Sin embargo, si la evolución de su programa en el futuro puede llevar a un cambio de contenedor, debe atenerse a los iteradores y usar std :: distance, que está garantizado para funcionar con todos los iteradores estándar.

Otros consejos

El uso de std :: distance es un poco más genérico, ya que funciona para todos los iteradores, no solo para los iteradores de acceso aleatorio. Y debería ser tan rápido como It - vec.begin () en caso de iteradores de acceso aleatorio.

It - vec.begin () es básicamente una aritmética de punteros.

std :: distance (vec.begin (), it) le dará el índice al que apunta, asumiendo que apunta a vec .

Carl

Volver al bucle indexado.

Básicamente, en el 90% de los casos, los iteradores son superiores, este es uno de esos 10%. Al usar un iterador, el código se vuelve más complejo y, por lo tanto, más difícil de entender, cuando, en primer lugar, la razón para usar el iterador fue simplificar el código.

Te falta una solución: mantén un índice en caso de que lo necesites, pero no lo uses como condición de bucle. También funciona en listas, y los costos (por bucle) son O (n) y un registro adicional.

Siempre tenderé a mantener los iteradores por motivos de desarrollo futuro.

En el ejemplo anterior, si tal vez decidiste cambiar std :: vector por std :: set (quizás necesitabas una colección única de elementos), el uso de iteradores y distance () continuaría funcionando.

Estoy bastante seguro de que cualquier problema de rendimiento se optimizaría hasta el punto de que sea insignificante.

Para los vectores, siempre uso el método entero. Cada índice en el vector es la misma velocidad que una búsqueda de matriz. Si voy a utilizar mucho el valor, creo una referencia a él, para mayor comodidad.

Los iteradores vectoriales

pueden ser un poco más rápidos que un índice en teoría, ya que utilizan aritmética de punteros para recorrer la lista. Sin embargo, generalmente encuentro que la legibilidad vale la diferencia mínima en tiempo de ejecución.

Uso iteradores para otros tipos de contenedores, y algunas veces cuando no se necesita la variable de bucle. Pero si necesita la variable de bucle, no está haciendo nada más que hacer que su bucle sea más difícil de escribir. (No puedo esperar al auto de c ++ 0x ..)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top