recorrer que iteradores iterador implementar c++ performance

c++ - que - Diferencia de rendimiento entre++ iterador e iterador++?



recorrer list integer java (7)

Eche un vistazo a este http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=171881

Mi compañero de trabajo afirma que para los tipos de objetos, el preincremento es más eficiente que el incremento posterior

p.ej

std::vector<std::string> vec; ... insert a whole bunch of strings into vec ... // iterate over and do stuff with vec. Is this more efficient than the next // loop? std::vector<std::string>::iterator it; for (it = vec.begin(); it != vec.end(); ++it){ } // iterate over and do stuff with vec. Is this less efficient than the previous loop? std::vector<std::string>::iterator it; for (it = vec.begin(); it != vec.end(); it++){ }


El postincremento debe devolver el valor que el iterador tenía ANTES de que se incrementara; por lo tanto, ese valor anterior debe copiarse en algún lugar antes de modificarlo con el incremento apropiado, para que esté disponible para devolverlo. El trabajo adicional puede ser un poco o mucho, pero ciertamente no puede ser menor que cero, en comparación con un preincremento, que simplemente puede realizar el incremento y luego devolver el valor que se acaba de modificar, sin copiar // guardar // etc necesario.

Por lo tanto, a menos que DEBE tener un postincremento específico (porque está usando el "valor antes del incremento" de alguna manera), siempre debe usar el preincremento en su lugar.


En serio, a menos que realmente tenga problemas de rendimiento debido a las llamadas post-incremento en lugar de pre-incremento LA DIFERENCIA DE RENDIMIENTO SÓLO IMPORTA EN CIRCUNSTANCIAS MUY RARAS .

Actualizar

Por ejemplo, si su software es una simulación del clima y el operator++ hace que la simulación avance un paso (es decir, la ++simulation le da el siguiente paso en la simulación, mientras que la simulation++ hace una copia del paso actual en la simulación, avanza la simulación, y luego le entrega la copia), entonces el rendimiento será un problema.

De manera más realista, en un comentario, el interrogador original menciona que estamos discutiendo un proyecto integrado con (aparentemente) requisitos de tiempo real. En ese caso, debe mirar su implementación específica. Dudo seriamente que tengas ralentizaciones notables a través de un std::vector con post-incremento en lugar de pre-incremento, aunque no he evaluado ninguna implementación de STL en esta materia.

No elija uno sobre el otro por razones de rendimiento. Elija uno sobre el otro por razones de claridad / mantenimiento. Personalmente, prefiero pre-incrementar porque generalmente no me importa lo que era el valor antes de incrementar.

Si su cerebro explota cuando ve ++i lugar de i++ , puede ser el momento de considerar ir a una línea de trabajo diferente.


He leído que no hace ninguna diferencia con los compiladores que tienen un optimizador decente. Como la lógica general del bucle es la misma para ambos, tiene sentido utilizar un incremento previo como un buen hábito de programación. De esa manera, si el programador encuentra el compilador "subóptimo", el mejor resultado está asegurado.


Los operadores de incremento predeterminados se verán así:

class X { X operator++(int) // Post increment { X tmp(*this); this->operator++(); // Call pre-increment on this. return tmp; } X& operator++() // Pre increment { // Do operation for increment. return *this; } };

Observe que el incremento posterior se define en términos del incremento previo. Así que Post-increment hace el mismo trabajo más un poco más. Por lo general, esto es construir una copia y luego devolver la copia a través de una copia (tenga en cuenta que el pre-incremento puede devolverse a sí mismo por referencia, pero el Post-incremento no puede).


Para los tipos primitivos, solía hacer esto. Antes, en 1998/1999, conseguía un aumento del 10% en muchos programas en Visual Studio. Poco después de eso, arreglaron su optimizador. El operador de incremento posterior creó una variable en la pila, copió el valor, incrementó la fuente y luego eliminó la variable de la pila. Una vez que los optimizadores detectaron que no se estaba utilizando, el beneficio desapareció.

La mayoría de las personas no dejaron de codificar de esa manera. :) Me tomó unos años.

Para los objetos, no estoy seguro de cómo funcionaría eso. Supongo que se requeriría un operador de copia para una verdadera implementación del incremento de publicación. Tendría que hacer una copia y usar la copia para las operaciones e incrementar la fuente.

Jacob


Sé que esto es como "vuelo de hangar" en la aviación. Estoy seguro de que es puramente académico, y sabes que si hace una gran diferencia necesitas volver a pensar tu código.

Ejemplo: recibí un comentario sobre una respuesta que le di a una pregunta sobre el ajuste de rendimiento, y fue así:

Persona: Probé su método de detener aleatoriamente y mirar la pila de llamadas. Lo hice varias veces, pero no tiene sentido. Todo el tiempo, es profundo en algún código de incremento de iterador. ¿De qué sirve eso?

Yo: ¡Eso es genial! Significa que casi todo tu tiempo va a incrementar iteradores. Solo mira más arriba en la pila y ve de dónde viene. Reemplace eso con un simple incremento de enteros, y obtendrá una aceleración masiva .

Por supuesto, es posible que prefiera la belleza del incremento del iterador, pero es bastante fácil averiguar si le está costando mucho rendimiento.