Pregunta

Esta es una pregunta que se refiere a cómo BOOST_FOREACH comprueba su terminación de bucle

cout << "Testing BOOST_FOREACH" << endl;
vector<int> numbers; numbers.reserve(8);
numbers.push_back(1); numbers.push_back(2); numbers.push_back(3);
cout << "capacity = " << numbers.capacity() << endl;
BOOST_FOREACH(int elem, numbers)
{
    cout << elem << endl;
    if (elem == 2) numbers.push_back(4); 
}
cout << "capacity = " << numbers.capacity() << endl;

da la salida

Testing BOOST_FOREACH
capacity = 8
1
2
3
capacity = 8

Pero, ¿qué pasa con el número 4 que se insertó a mitad del ciclo? Si cambio el tipo a una lista, el número que se acaba de insertar se repetirá. La operación vectorial push_back invalidará cualquier puntero SI se requiere una reasignación, sin embargo eso no está sucediendo en este ejemplo. Entonces, la pregunta que supongo es ¿por qué el iterador end () parece ser evaluado solo una vez (antes del bucle) cuando se usa vector pero tiene una evaluación más dinámica cuando se usa una lista?

¿Fue útil?

Solución

  

Bajo las cubiertas, BOOST_FOREACH utiliza   iteradores para atravesar el elemento   secuencia. Antes de que se ejecute el bucle,   el iterador final se almacena en caché en un local   variable. Esto se llama elevación, y   Es una optimización importante. Eso   asume, sin embargo, que el fin   El iterador de la secuencia es estable. Eso   Normalmente es, pero si modificamos el   secuencia mediante la adición o eliminación   elementos mientras estamos iterando sobre   Es decir, podemos terminar levantándonos a nosotros mismos.   en nuestro propio petardo.

http://www.boost.org/ doc / libs / 1_40_0 / doc / html / foreach / pitfalls.html

Si no desea que el iterador end () cambie, cambie el tamaño del vector en lugar de reservar.

http://www.cplusplus.com/reference/stl/vector/resize /

Tenga en cuenta que no querrá hacer push_back sino usar el operador [] en su lugar. Pero ten cuidado de salir de los límites.

Otros consejos

La pregunta se planteó en los comentarios sobre por qué el tiempo de ejecución de depuración de Microsoft genera una afirmación durante la iteración sobre el vector pero no sobre la lista. La razón es que insert se define de manera diferente para list y vector (tenga en cuenta que push_back es solo un inserte al final de la secuencia).

De acuerdo con el estándar C ++ (ISO / IEC 14882: 2003 23.2.4.3, modificadores de vectores ):

  

[en la inserción], si no ocurre una reasignación, todos los iteradores y referencias antes del punto de inserción seguirán siendo válidos.

(23.2.2.3, modificadores de lista ):

  

[insertar] no afecta la validez de los iteradores y las referencias.

Por lo tanto, si usa push_back (y está seguro de que no causará una reasignación), está bien que cualquiera de los contenedores continúe usando su iterador para iterar sobre el resto de la secuencia.

En el caso del vector, sin embargo, es comportamiento indefinido usar el iterador end que obtuvo antes del push_back .

Esta es una respuesta indirecta a la pregunta; Es una respuesta directa a la discusión en los comentarios de la pregunta.

el foreach de boost se terminará cuando sea iterador == números.end ()

Sin embargo, tenga cuidado, llamar push_back puede / invalidará cualquier iterador actual que tenga.

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