Soy nuevo en el lenguaje C ++. He comenzado a usar vectores, y he notado que en todo el código veo iterar a través de un vector a través de índices, el primer parámetro del for
bucle siempre es algo basado en el vector. En Java, podría hacer algo como esto con una ArrayList:
for(int i=0; i < vector.size(); i++){
vector[i].doSomething();
}
¿Hay alguna razón por la que no veo esto en C ++? ¿Es una mala práctica?
c++
coding-style
for-loop
iterator
Flynn
fuente
fuente
std::vector<int>::size_type i = 0;
o tal vezstd::vector<int>::iterator it = vector.begin();
?std::vector
? , la pregunta real que se pregunta aquí es: ¿Hay alguna razón por la que no veo esto en C ++? ¿Es una mala práctica? aka ¿Por qué siempre veo código en C ++ que usa iteradores mientras iterastd::vector
?Respuestas:
No. No es una mala práctica, pero el siguiente enfoque hace que su código tenga cierta flexibilidad .
Por lo general, antes de C ++ 11, el código para iterar sobre elementos de contenedor usa iteradores, algo así como:
Esto se debe a que hace que el código sea más flexible.
Todos los contenedores de biblioteca estándar admiten y proporcionan iteradores. Si en un momento posterior del desarrollo necesita cambiar a otro contenedor, entonces este código no necesita ser cambiado.
Nota: Escribir código que funcione con todos los contenedores de biblioteca estándar posibles no es tan fácil como parece.
fuente
auto
.La razón por la que no ve tal práctica es bastante subjetiva y no puede tener una respuesta definitiva, porque he visto muchos de los códigos que utilizan su manera mencionada en lugar de
iterator
código de estilo.Los siguientes pueden ser motivos de personas que no consideran la
vector.size()
forma de bucle:size()
cada vez en la condición de bucle. Sin embargo, no es un problema o se puede solucionar de manera trivialstd::for_each()
sobre elfor
ciclo en sístd::vector
a otro (por ejemplomap
,list
) también exigir el cambio del mecanismo de bucle, porque no todos los soporte de contenedorsize()
estilo de bucleC ++ 11 proporciona una buena instalación para moverse a través de los contenedores. Eso se llama "rango basado para bucle" (o "mejorado para bucle" en Java).
Con un código pequeño, puede atravesar el completo (obligatorio)
std::vector
:fuente
#pragma omp parallel for
.La forma más limpia de iterar a través de un vector es a través de iteradores:
o (equivalente a lo anterior)
Antes de C ++ 0x, debe reemplazar auto por el tipo de iterador y usar funciones miembro en lugar de comenzar y finalizar funciones globales.
Esto probablemente es lo que has visto. En comparación con el enfoque que menciona, la ventaja es que no depende en gran medida del tipo de
vector
. Si cambiavector
a una clase diferente de "tipo de colección", su código probablemente seguirá funcionando. Sin embargo, también puede hacer algo similar en Java. No hay mucha diferencia conceptual; C ++, sin embargo, utiliza plantillas para implementar esto (en comparación con los genéricos en Java); por lo tanto el enfoque de trabajo para todos los tipos para los quebegin
yend
funciones están definidas, incluso para tipos no clase, tales como matrices estáticas. Vea aquí: ¿Cómo funciona el rango basado en trabajo para matrices simples?fuente
begin
yend
, sin embargo, es una línea.auto
por otro lado sería bastante complicado.La forma correcta de hacerlo es:
Donde T es el tipo de la clase dentro del vector. Por ejemplo, si la clase era CActivity, simplemente escriba CActivity en lugar de T.
Este tipo de método funcionará en cada STL (no solo en vectores, que es un poco mejor).
Si aún desea usar índices, la forma es:
fuente
std::vector<T>::size_type
siempresize_t
? Ese es el tipo que siempre uso para ello.Hay un par de fuertes razones para usar iteradores, algunos de los cuales se mencionan aquí:
Cambiar contenedores más tarde no invalida su código.
es decir, si pasa de un std :: vector a un std :: list, o std :: set, no puede usar índices numéricos para obtener su valor contenido. Usar un iterador sigue siendo válido.
Captura de tiempo de ejecución de iteración no válida
Si modifica su contenedor en el medio de su ciclo, la próxima vez que use su iterador arrojará una excepción de iterador no válida.
fuente
Me sorprendió que nadie mencionara que iterar a través de una matriz con un índice entero facilita la escritura de código defectuoso al suscribir una matriz con el índice incorrecto. Por ejemplo, si tiene bucles anidados utilizando
i
yj
como índices, podría subíndice incorrectamente una matriz enj
lugar dei
e introducir una falla en el programa.Por el contrario, las otras formas enumeradas aquí, a saber, el
for
bucle basado en rango y los iteradores, son mucho menos propensos a errores. La semántica del lenguaje y el mecanismo de verificación de tipo del compilador le impedirá acceder accidentalmente a una matriz usando el índice incorrecto.fuente
Con STL, los programadores utilizan
iterators
para atravesar contenedores, ya que iterador es un concepto abstracto, implementado en todos los contenedores estándar. Por ejemplo,std::list
no tieneoperator []
en absoluto.fuente
El uso del operador automático realmente facilita su uso, ya que uno no tiene que preocuparse por el tipo de datos y el tamaño del vector o cualquier otra estructura de datos
Vector iterativo usando auto y para loop
Salida:
También puede usar este método para iterar conjuntos y listas. Usando automático detecta automáticamente el tipo de datos utilizado en la plantilla y le permite utilizar la misma. Así que, incluso si tuviéramos una
vector
destring
ochar
la misma sintaxis funcionará bienfuente
La forma correcta de iterar el ciclo e imprimir sus valores es la siguiente:
fuente
Aquí hay una forma más simple de iterar e imprimir valores en el vector.
fuente
fuente