c++ - ++ i o i++ en bucles?
for-loop post-increment (9)
Como otros ya han notado, el preincremento suele ser más rápido que el incremento posterior para los tipos definidos por el usuario. Para comprender por qué esto es así, observe el patrón de código típico para implementar ambos operadores:
Foo& operator++()
{
some_member.increase();
return *this;
}
Foo operator++(int dummy_parameter_indicating_postfix)
{
Foo copy(*this);
++(*this);
return copy;
}
Como puede ver, la versión de prefijo simplemente modifica el objeto y lo devuelve por referencia.
La versión de postfix, por otro lado, debe hacer una copia antes de que se realice el incremento real, y luego esa copia se copiará a la persona que llama por su valor. Es obvio desde el código fuente que la versión de postfix debe hacer más trabajo, porque incluye una llamada a la versión de prefijo: ++(*this);
Para los tipos incorporados, no hace ninguna diferencia siempre que descartes el valor, es decir, siempre que no incrustes ++i
o i++
en una expresión más grande como a = ++i
o b = i++
.
Posible duplicado:
¿Hay una diferencia de rendimiento entre i ++ y ++ i en C ++?
¿Hay alguna razón por la cual algunos programadores escriben ++i
en un bucle for normal en lugar de escribir i++
?
Con enteros, es preferencia.
Si la variable de bucle es una clase / objeto, puede marcar la diferencia (solo los perfiles pueden indicarle si se trata de una diferencia significativa), ya que la versión posterior al incremento requiere que cree una copia de ese objeto que se descarta.
Si crear esa copia es una operación costosa, está pagando ese gasto una vez por cada vez que pasa por el ciclo, sin ningún motivo.
Si adquiere el hábito de usar siempre ++i
en los bucles, no necesita detenerse y pensar si lo que está haciendo en esta situación particular tiene sentido. Tú siempre lo eres.
Hay una razón para esto: rendimiento. i ++ genera una copia, y eso es un desperdicio si lo descarta inmediatamente. Por supuesto, el compilador puede optimizar esta copia si i
soy un primitivo, pero no puede si no lo es. Ver esta pregunta
Ningún compilador que valga la pena en sal se ejecutará de manera diferente entre
for(int i=0; i<10; i++)
y
for(int i=0;i<10;++i)
++ i e i ++ tienen el mismo costo . Lo único que difiere es que el valor de retorno de ++ i es i + 1, mientras que el valor de retorno de i ++ es i.
Entonces, para aquellos que prefieren ++ i, probablemente no haya una justificación válida, solo preferencia personal.
EDITAR: Esto es incorrecto para las clases, como se dice en cada otra publicación. i ++ generará una copia si soy una clase.
Para enteros, no hay diferencia entre el incremento previo y posterior.
Si i
es un objeto de una clase no trivial, generalmente se prefiere ++i
, porque el objeto se modifica y luego se evalúa, mientras que i++
modifica después de la evaluación, por lo que requiere una copia.
Preferencia personal.
Generalmente. A veces es importante pero, para no parecer un idiota aquí, pero si tiene que preguntar, probablemente no lo haga.
cuando usas postfix crea una instancia en más objetos en la memoria. Algunas personas dicen que es mejor usar el sufijo operador en el ciclo
++i
es ligeramente más eficiente debido a su semántica:
++i; // Fetch i, increment it, and return it
i++; // Fetch i, copy it, increment i, return copy
Para índices de tipo int, la ganancia de eficiencia es mínima (si la hay). Para los iteradores y otros objetos de mayor peso, evitar esa copia puede ser una verdadera ganancia (especialmente si el cuerpo del bucle no contiene mucho trabajo).
Como ejemplo, considere el siguiente ciclo utilizando una clase BigInteger teórica que proporciona números enteros de precisión arbitraria (y, por tanto, algún tipo de elemento interno similar a un vector):
std::vector<BigInteger> vec;
for (BigInteger i = 0; i < 99999999L; i++) {
vec.push_back(i);
}
Esa operación de i ++ incluye la construcción de copias (es decir, operador nuevo, copia de dígito por dígito) y la destrucción (eliminación de operador) para un bucle que no hará más que esencialmente hacer una copia más del objeto de índice. Básicamente, ha duplicado el trabajo por realizar (y la mayor fragmentación de la memoria lo más probable es que lo haga) simplemente usando el incremento de postfijo donde el prefijo hubiera sido suficiente.
++i
es un pre-incremento; i++
es un incremento posterior.
La desventaja del incremento posterior es que genera un valor adicional; devuelve una copia del valor anterior al modificar i
. Por lo tanto, debes evitarlo cuando sea posible.