¿Cuál es el mal uso común de usar contenedores STL con iteradores?¿Cuál es el mal uso común de usar contenedores STL con iteradores?
Respuesta
Olvidar que los iteradores a menudo se invalidan si cambia el contenedor insertando o borrando miembros del contenedor.
Para muchas grandes consejos sobre el uso de STL I altamente recomiendan libro de Scott Meyers "STL eficaz" (sanitised Amazon link)
Post-incrementarse cuando pre-incrementación va a hacer.
No puedo decir que esto sea un gran problema ya que no compromete la corrección del código, y seguramente un compilador de optimización decente generará código idéntico cada vez el valor original de pre-incremento de i ++ no se usa? (Tenga en cuenta que siempre hago pre-inc por si acaso ...) FTR: No lo hice -1 (tampoco lo hizo +1 ...). –
@j_random_hacker, estoy totalmente de acuerdo en que no es gran cosa, pero es una expresión de iterador de STL común. La pregunta no especificaba qué tipos de temas específicos le preocupaban. –
El compilador no puede necesariamente generar código idéntico, dependiendo de qué es realmente el iterador. i ++ genera un valor temporal, que no siempre puede optimizarse. ++ solo hago el incremento. –
La verificación del rango final debe estar utilizando! = Y no <, ya que no se garantiza el orden de los punteros.
Ejemplo:
for(it = list.begin(); it != list.end(); ++it)
{
// do stuff
}
¡Ay! La implementación de la Biblioteca estándar de C++ debe utilizar (typedefs de) tipos de punteros sin procesar como iteradores; por esta razón, es mucho más seguro implementar todos los iteradores como tipos distintos que envuelven punteros, con sobrecargas de operador adecuadas (por ejemplo, para el operador ==() pero no el operador <()). –
Sí, hace un tiempo que hice C++ para ser sincero. Nunca tuve problemas con él, ya que usaba principalmente vectores. Esta es una de las cosas que recuerdo de Exceptional C++ de Herb Sutter. (O algún otro libro similar) –
Tiene un error tipográfico: debe comparar "it! = List.end()", no "it! = List.end". De lo contrario, estás comparando con la dirección de una función. – Tom
Su uso sin necesidad de leer el libro "STL eficaz" por Scott Meyers. :) De Verdad. Esto hace que la mayoría de los bichos estúpidos desaparezcan.
Además de tener muchos buenos consejos y ejemplos sobre la mejor manera de utilizar el STL. –
Algunos otros:
Conversión de un iterador inverso en un iterador de base sin recordar que el iterador ahora será uno de los elementos más allá de la que estaba señalando.
Intentando usar algoritmos que requieren un iterador de acceso aleatorio con iteradores de cosas como conjuntos y mapas.
recomienda modificar la clave de una entrada de mapa con un iterador no constante (esto sucede a construir sobre VS.Net, pero no lo hará con GCC)
continuación adecuada después de erase()
.
Suponiendo:
Container::iterator i = cont.begin(), iEnd = cont.end();
Por ejemplo en std::map
, esto no es una buena idea:
for (; i != iEnd; ++i) {
if (i->second.eraseCondition()) {
cont.erase(i);
}
}
esto funcionaría:
for (; i != iEnd;) {
Container::iterator temp = i;
++temp;
if (i->second.eraseCondition()) {
cont.erase(i);
}
i = temp;
}
Y esto también:
for (; i != iEnd;) {
if (i->second.eraseCondition()) {
cont.erase(i++);
}
else {
++i;
}
}
Ha sido demasiadas veces realmente que he tenido que aplicar estas correcciones en algún código de producción :(
Para esto, debe usar std :: remove_if para evitar este tipo de errores. –
@Billy: Pero nadie lo hace porque sin lambdas tu código parece prolijo y estúpido. –
@ Zan: 1. ¿Alguna estadística que respalde eso? 2. No sé ustedes, pero tomaré un código de apariencia un poco "estúpido" para convertir un algoritmo O (n^2) en un algoritmo O (n). –
El uso de un auto_ptr dentro de un contenedor, por ejemplo,
list<auto_ptr<int> > foo;
Afortunadamente, muchas implementaciones auto_ptr estos días están escritos para hacer que esto sea imposible.
Nota: Use boost :: shared_ptr <> en lugar de std :: auto_ptr <> si desea almacenarlos en un contenedor. – Frank
Esto no es solo un problema con los contenedores STL: el contenedor modyfing al iterar sobre él casi siempre genera problemas.
Esta es una fuente muy común de errores en los juegos: la mayoría de los bucles de juego consisten en iterar sobre cada objeto del juego haciendo algo. Si esto algo agrega o borra elementos del contenedor de objetos del juego, seguramente habrá errores.
Solución: tenga dos contenedores, objectsToDelete y objectsToAdd, en el código del juego agregue objetos a esos contenedores y actualice el contenedor de objetos del juego solo después de iterar sobre él.
objetsToAdd puede establecerse para garantizar que no eliminaremos nada más de una vez.
objectsToDelete puede ser cola si se puede construir objetos sin agregarlo a juego contenedor de objetos, o puede ser alguna otra clase (ObjectCreateCommand?) Si el código asume esa instancia de objeto siempre se añade al juego de objetos contenedores directamente después de la creación (por ejemplo en constructor).
Tengo que estar más de acuerdo con este: he visto el bucle de objetos infinitamente creciente muchas veces. También se ve la omisión del elemento después del elemento eliminado e incluso el reprocesamiento del elemento antes del elemento eliminado. –
list<int> l1, l2;
// ...
for_each(l1.begin(), l2.end(), do_it());
- 1. Escribiendo stl compatible con iteradores
- 2. contenedores adaptadores no son compatibles con los iteradores
- 3. ¿Qué es el STL?
- 4. Contenedores OpenCV, Matlab y STL
- 5. ¿Por qué hay una separación de algoritmos, iteradores y contenedores en C++ STL
- 6. const y STL contenedores
- 7. ¿Cómo uso contenedores C++ STL en la aplicación My iPhone?
- 8. Cómo aplanar los iteradores de contenedores anidados?
- 9. Iteradores entendimiento en la STL
- 10. Compatibilidad binaria de contenedores STL
- 11. Inspeccionando contenedores STL en XCode
- 12. Encabezados hacia adelante para contenedores STL
- 13. VC++ permite usar tipos const para contenedores STL. ¿Por qué?
- 14. algoritmo de STL más utilizado, predicados, iteradores
- 15. ¿Transferir la propiedad dentro de contenedores STL?
- 16. Depuración de contenedores C++ STL en Windbg
- 17. ¿Cuál es el punto de STL?
- 18. iteración de contenedores STL encapsulados encapsulados
- 19. Uso de std :: unique_ptr con contenedores estándar
- 20. Estructuras de datos equivalentes de contenedores STL
- 21. STL asignación de contenedores y punteros const
- 22. const y no const en contenedores STL
- 23. lambda + for_each + eliminar en contenedores STL
- 24. ¿Cuándo tiene sentido utilizar unique_ptr con contenedores STL? (C++ 11)
- 25. ¿Cómo se implementa end() en contenedores STL?
- 26. contenedores STL en la pila y el montón
- 27. ¿Cuál es el tiempo de vida y la validez de los iteradores de C++?
- 28. ¿Cómo copian los objetos STL los contenedores?
- 29. Uso de iteradores sobre índices de matriz
- 30. ¿Es imposible usar el mapa stl con struct?
En general, estoy de acuerdo, pero es posible interpretar su afirmación como "los iteradores son * siempre * invalidados por inserciones o eliminaciones". Los iteradores de vectores nunca se invalidan borrando un elemento * later *, y ni las inserciones ni las eliminaciones de otros elementos anulan la lista, establecen y asignan iteradores. –
@j_random_hacker: es cierto, voy a editar mi respuesta –
si es posible agregue un código – yesraaj