2010-02-04 35 views
10

que he leído aquí y en otros lugares que cuando se repite una std :: vector uso de índices, debe:Iterar std :: vector múltiple

std::vector <int> x(20,1); 
for (std::vector<int>::size_type i = 0; i < x.size(); i++){ 
    x[i]+=3; 
} 

Pero lo que si usted está iterando dos vectores de diferentes tipos:

std::vector <int> x(20,1); 
std::vector <double> y(20,1.0); 
for (std::vector<int>::size_type i = 0; i < x.size(); i++){ 
    x[i]+=3; 
    y[i]+=3.0; 
} 

¿es seguro asumir que

std::vector<int>::size_type

es O f del mismo tipo que

std::vector<double>::size_type 

?

¿Sería seguro simplemente usar std :: size_t?

Gracias.

+0

Si se le ha enseñado sobre la iteración gusta esto, te han enseñado mal Además de 'i ++' que cualquier compilador decente debería optimizar a '++ i', todavía se llama a' x.size() 'en cada vuelta del ciclo, que si no es trivial y no está en línea es un desperdicio. –

+0

@Matthieu, solo un ejemplo rápido y sucio para ilustrar mi pregunta. También debería usar iteradores y no hacerlo por índice. – Mark

Respuesta

7

Sí, para casi cualquier propósito práctico, puede simplemente usar std :: size_t. Aunque había (más o menos) una intención de que los diferentes contenedores pudieran usar diferentes tipos para sus tamaños, aún así se garantiza que (al menos para los contenedores estándar) size_type sea lo mismo que size_t.

Alternativamente, usted podría considerar el uso de un algoritmo, algo así como:

std::transform(x.begin(), x.end(), x.begin(), std::bind2nd(std::plus<int>(), 3)); 
std::transform(y.begin(), y.end(), y.begin(), std::bind2nd(std::plus<double>(), 3.0)); 
2

En general, el estándar C++ no ofrece tales garantías: ni la igualdad de size_types para contenedores con parámetros diferentes, ni la igualdad a size_t.

+0

+1. Y estaba en lo cierto, la garantía 'std :: size_t' es solo para asignadores. Pensé que 'std :: vector :: size_type' tenía que ser igual a' Allocator :: size_type', pero aparentemente no. – avakar

+0

@avakar: La situación es que el asignador estándar usa size_t para su size_type, y todas las implementaciones conocidas de los contenedores estándar pasan el tamaño de tipo desde su asignador asociado. Como resultado, a menos que escriba su propio asignador, será size_t. Desde una perspectiva práctica, size_t esencialmente siempre va a funcionar, independientemente de lo que usen como size_type, p. Ej. ':: operator new' usa size_t para el tamaño de la asignación, y esencialmente todas las otras asignaciones pasan por eso (al menos de manera predeterminada). –

1

Bueno, creo que:

for (std::vector<int>::size_type i = 0; i < x.size(); i++){ 

es algo de un consejo de perfección - están esperando sus vectores a ser realmente gigantesco? Personalmente, uso unsigned int, sin problemas.

Y ahora supongo que el downvotes comenzarán ...

+0

@Neil, amo el "consejo de la perfección". Estaba usando unsigned int pero leyendo cosas como esta: http://stackoverflow.com/questions/409348/iteration-overvector-in-c, nos preocupa. Probablemente una preocupación innecesaria. – Mark

+0

@Neil: nunca vivirás tanto tiempo - nadie quiere ser culpado perfeccionista Supongo que :-D –

+2

@Mark Si estás usando un tipo sin firmar, estás bien, en mi humilde opinión. La respuesta de litb a la pregunta que vinculó es (por supuesto) correcta, pero realmente te debe gustar teclear (en ambos sentidos) para usar size_type. –

2

Creo que se puede asumir con seguridad que size_type es un entero sin signo nonegative. No puedes confiar mucho más que eso. Claro, la mayoría de los contenedores tienen un size_type que es lo mismo que size_t pero no hay garantías.

La documentación de SGI y esta fuente http://www.cplusplus.com/reference/stl/vector/ parecen estar de acuerdo en el punto.

También es posible que desee echar un vistazo a esta solución para su problema: http://rosettacode.org/wiki/Loop_over_multiple_arrays_simultaneously#C.2B.2B

espero que esto ayude.

+0

@batbrat, buen enlace a rosettacode, muy útil. – Mark

+0

¡Me alegro de que haya sido útil! – batbrat

-1

Debe utilizar iteradores en lugar

std::vector <int> x(20,1); 
std::vector <double> y(20,1.0); 
std::vector<double>::iterator j = y.begin(); 
for (std::vector<int>::iterator i = x.begin(); i != x.end(); ++i){ 
    *i +=3; 
    *j +=3.0; 
    ++j; 
} 

Porque no hay ninguna garantía de que u size_type sería el mismo tipo interno, de todos modos, por std::vector se podía repetir usando unsigned int

+1

¿Por qué no incrementar 'j' en el cuerpo de control? Y tú también sufres por no usar una variable 'max' o' end' para verificar el final de la iteración ... mantente con 'for_each' en realidad;) –

+0

@MatthieuM, ¿cómo podrías usar foreach cuando necesites iterar en dos? diferentes vectores? Obviamente, este ejemplo es trivial y los bucles se pueden separar, no puedo pensar en una forma de hacerlo para x [i] = y [i] + 3 –