2009-07-02 9 views
24

Duplicar posible:
Is there a performance difference between i++ and ++i in C++?Incrementando iteradores: ¿es más eficiente que él ++?

Estoy escribiendo un programa en el que un repetidor se utiliza para recorrer un std :: vector. Alguien me dijo que hacer + + en la declaración for lleva a un código más eficiente. En otras palabras, están diciendo que:

for (vector<string>::iterator it=my_vector.begin(); it != my_vector.end(); ++it) 

corre más rápido que

for (vector<string>::iterator it=my_vector.begin(); it != my_vector.end(); it++) 

es esto cierto? Si lo es, ¿cuál es el motivo de la mejora de la eficiencia? Todo lo que hace ++/++ es mover el iterador al siguiente elemento en el vector, ¿no es así?

+7

Ver: http://stackoverflow.com/questions/24901/ – Shog9

+2

Un duplicado exacto, pero la carrera de rep está activada de todos modos. – macbirdie

+1

Esto se trata de iteradores, al igual que las respuestas. Las otras preguntas parecen preguntar acerca de la diferencia general. Creo que son preguntas relacionadas, pero no duplicados exactos. –

Respuesta

2

A veces sí. Con algunos se optimizará y será lo mismo. Para std :: vector <> (y otros std-iterators) lo más probable es que se optimice para que sea el mismo.

0

Sí. Por lo que recuerdo, ++ es más eficiente que ++, porque ++ crea un objeto temporal, mientras que ++ no lo hace.

1

sí ++ es más eficiente porque ++ necesita devolver una copia del objeto y luego incrementarse.

31

La razón detrás de que el preincremento sea más rápido es que el incremento posterior tiene que hacer una copia del valor anterior para devolver. Como GotW #2 lo expresó, "El preincremento es más eficiente que el postincremento, porque para postincremento, el objeto debe incrementarse y luego devolver un valor temporal que contiene su valor anterior. Tenga en cuenta que esto es cierto incluso para construcciones internas como int".

GotW #55 proporciona la forma canónica de postincremento, lo que muestra que tiene que ver preincremento además de algunos trabajos más:

T T::operator++(int) 
{ 
    T old(*this); // remember our original value 
    ++*this;  // always implement postincrement 
        // in terms of preincrement 
    return old;  // return our original value 
} 

Como otros han señalado, es posible que algunos compilador para optimizar esta distancia, en algunos casos, pero si no está utilizando el valor de retorno, es una buena idea no confiar en esta optimización. Además, es probable que la diferencia de rendimiento sea muy pequeña para los tipos que tienen constructores de copia triviales, aunque creo que el uso de preincremento es un buen hábito en C++.

+2

Tenga en cuenta que los compiladores decentes optimizarán la copia del antiguo valor si nunca se usa. – Novelocrat

+2

Exactamente: no se puede prometer que el preincremento sea más eficiente que postincremento, porque (a) el estándar no lo requiere, y (b) es bastante fácil inventar combinaciones de código fuente y compilador donde los dos son igualmente eficientes. –

+0

Pero puede suponer que el preincremento es al menos tan eficiente como postincremento. Entonces, ¿por qué no usarlo siempre, cuando de otro modo son equivalentes? –

2

Existe la posibilidad de que ++ cree una copia temporal.

Además, en C++, existe la posibilidad de que alguien haya sobrecargado el operador postincrement.

Ambas cosas pueden disminuir el rendimiento vs preincremento. Ninguna de las dos tendrá importancia en la práctica. La mayoría de los compiladores optimizarán la copia temporal, en particular, ya que no hay efectos secundarios en la tercera expresión de su bucle For.

6

Es poco probable que haga una diferencia para un vector.

En general, ++it es muy poco probable que sea más lento que it++ (suponiendo una aplicación sensata, si están sobrecargados), y sólo podría ser más rápido. El motivo es que si la clase de iterador en sí misma es compleja, entonces porque it++ tiene que devolver el valor antes de que it se incremente, la implementación generalmente hará una copia.

Los iteradores vectoriales son probablemente "solo punteros" (en construcciones optimizadas sin depuración), y ambos operator++ s estarán en línea. Como el valor de retorno no se utiliza, la copia generalmente se eliminará. Por lo tanto, no hará ninguna diferencia. Tengo la costumbre de escribir ++it porque:

1) Algún día podría hacer una diferencia, para algún tipo de iterador, y no quiero tener que hacer algo especial para ese tipo.

2) Personalmente creo que el operador del prefijo expresa más claramente la intención: "incrementarlo", en lugar de "usarlo y luego incrementarlo".

+0

Tendría que decir que el número 2 para mí era más confuso de ver ++ que de ++. Por ejemplo, al mirar un int int para el bucle, for (int i = 0; i <10; i ++) me dice que tengo el entero i que establecí en 0 (a propósito porque lo quiero 0 la primera vez), quiero hacer esto siempre y cuando yo tenga menos de 10, y quiero incrementar i por ONE cada vez que termine el ciclo). entonces para ver ++ fue muy confuso para mí la primera vez, recuerdo haber pensado (¿por qué querrías repetir ANTES de hacer algo? ¿por qué no lo configurabas solo en lo que querías en lugar de 1 menos de lo que querías?) Lo entiendo ahora, pero todavía – Josh

+0

@Josh: bien, pero eso es solo una consecuencia de la completa confusión del recién llegado sobre cuándo se ejecuta la última parte del bucle for. Por supuesto, aún inicializas a 0, y todavía tiene valor 0 la primera vez a través del ciclo, 1 la segunda vez, etc., independientemente de si escribes '++ i' o' i ++ '. Francamente, si escribir '++ i' le pide al recién llegado que resuelva esa confusión más temprano que tarde, y entiende que la cláusula se ejecuta * después de * el cuerpo del bucle sin importar lo que contenga, entonces lo calificaría como un ventaja adicional para '++ i'! –

+0

Creo que debería llamar a los malos profesores de la escuela secundaria antes de irme a la universidad. Nos dijeron ++ quise decir que aumentaría antes de evaluar lo que está dentro del ciclo, e i ++ se incrementaría después de la evaluación de lo que hay dentro del ciclo. Si me hubieran dicho correctamente desde el principio, la confusión nunca habría existido. – Josh

2

se ++ realiza las siguientes operaciones:

  1. crear una copia de de ella
  2. incremento que
  3. devolverá el original (no incrementado) que

++ realiza la siguientes operaciones:

  1. incremento que
  2. retorno que

Porque ++ crea una copia, puede decirse que es "más lento". Sin embargo, cualquier compilador decente optimizará esta diferencia para la mayoría de los tipos definidos. Para algunos tipos definidos por el usuario, puede ser más rápido.

+0

¿Querías decir "lento"? – Gobe

Cuestiones relacionadas