variable una significa que prefijo postincremento postfijo operadores los incremento hay entre diferencias diferencia decremento c++ operators

una - que significa i++ en c++



¿Por qué usar++ i en lugar de i++ en los casos en que el valor no se usa en ninguna otra parte de la declaración? (7)

Soy muy consciente de que en C ++

int someValue = i++; array[i++] = otherValue;

tiene un efecto diferente en comparación con

int someValue = ++i; array[++i] = otherValue;

pero de vez en cuando veo sentencias con un prefijo incrementado en los bucles for o solo por su cuenta:

for( int i = 0; i < count; ++i ) { //do stuff }

o

for( int i = 0; i < count; ) { //do some stuff; if( condition ) { ++i; } else { i += 4; } }

En los dos últimos casos, el ++i parece un intento de producir código de aspecto inteligente. ¿Estoy supervisando algo? ¿Hay alguna razón para usar ++i lugar de i++ en los dos últimos casos?


Como notaste, no importa el resultado.

Hay una consideración de rendimiento para los tipos no primitivos.

También el uso semántico de preincremento suele ser más claro al mostrar la intención de una prueba cuando se usa el valor de retorno, por lo que es mejor usarlo habitualmente que post-incremento para evitar probar accidentalmente el valor antiguo.


El C ++ FAQ Lite tiene una buena discusión de i++ vs. ++i aquí:

[13.15] ¿Cuál es más eficiente: i ++ o ++ i?

En particular, con respecto a qué forma usar dentro de un bucle for , las preguntas frecuentes expresan una preferencia por ++i . Aquí está el texto:

Entonces, si está escribiendo i++ como una declaración en lugar de como parte de una expresión más grande, ¿por qué no escribir ++i lugar? Nunca pierdes nada, ya veces ganas algo. Los programadores de la antigua línea C están acostumbrados a escribir i++ lugar de ++i . Por ejemplo, dirán, for (i = 0; i <10; i++) .... Como esto usa i++ como una declaración, no como parte de una expresión más grande, entonces es posible que desee utilizar ++i lugar . Para la simetría, personalmente defiendo ese estilo incluso cuando no mejora la velocidad, por ejemplo, para los tipos intrínsecos y para los tipos de clase con operadores de postfix que devuelven el vacío.


Hay pocas razones para favorecer el pre-incremento sobre el post-incremento cuando se habla de tipos naturales como los enteros. El compilador normalmente es capaz de generar el mismo código en ambos casos de todos modos, asumiendo que usted no usa el valor de retorno. Esto no es cierto para los tipos más complejos, como los iteradores.


Hay una razón, y tiene que ver con los operadores sobrecargados. En una función postincremento sobrecargada, la función debe recordar el valor anterior del objeto, incrementarlo y luego devolver el valor anterior. En una función de preincremento, la función puede simplemente incrementar el objeto y luego devolver una referencia a sí misma (su nuevo valor).

En el caso de un entero, lo anterior probablemente no se aplicará porque el compilador conoce el contexto en el que se está realizando el incremento y generará el código de incremento apropiado en cualquier caso.


Mirar las posibles implementaciones de los dos operadores en código propio:

// Pre-increment T*& operator ++() { // Perform increment operation. return *this; } // Post-increment T operator ++(int) { T copy = *this; ++*this; return copy; }

El operador de postfix invoca al operador de prefijo para realizar su propia operación: por diseño y en principio, la versión del prefijo siempre será más rápida que la versión de postfix, aunque el compilador puede optimizar esto en muchos casos (especialmente para los tipos incorporados).

La preferencia por el operador de prefijo es por lo tanto natural; el otro es el que necesita una explicación: ¿por qué hay tanta gente intrigada por el uso del operador de prefijo en situaciones en las que no importa? Sin embargo, nadie se sorprende por el uso del operador de postfix.


Sí, por razones de rendimiento. En el caso de un incremento posterior, se debe hacer una copia de la variable i antes del incremento para que se pueda devolver el valor anterior (aunque no esté utilizando el valor de retorno). En caso de pre-incremento esta copia no es requerida.


Si ignoramos la fuerza del hábito, ''++ i'' es conceptualmente una operación más simple: simplemente agrega uno al valor de i, y luego lo usa.

i++ por otro lado, es "tomar el valor original de i , almacenarlo como temporal, agregar uno a i , y luego devolver el temporal". Requiere que mantengamos el valor anterior incluso después de que se haya actualizado.

Y como demostró Konrad Rudolph, puede haber costos de rendimiento al usar i++ con tipos definidos por el usuario.

Entonces, la pregunta es, ¿por qué no siempre el valor predeterminado es ++i ?

Si no tiene ninguna razón para usar `i ++ ´, ¿por qué hacerlo? ¿Por qué debería utilizar la operación por defecto, que es más complicada de razonar y puede ser más lenta de ejecutar?