++i vs i++ en C++: mismo resultado, distinto momento

Respuesta corta: ambos suman 1 a i. La diferencia es cuánto vale la expresión en sí: ++i devuelve el valor nuevo; i++ devuelve el viejo antes de incrementar. Solos en una línea, son idénticos.

Ejecuta esto — las dos variables arrancan iguales, y la única diferencia es pre- vs post-incremento:

#include <iostream>
using namespace std;

int main() {
    int i = 5;
    cout << "i++ gives: " << i++ << ", i is now " << i << endl;

    int j = 5;
    cout << "++j gives: " << ++j << ", j is now " << j << endl;
    return 0;
}

i++ imprimió 5 — el valor viejo — y solo después pasó a 6. ++j primero se volvió 6 e imprimió el valor nuevo. Esa es toda la diferencia: el valor de la expresión.

Qué hace cada uno, paso a paso

¿En un bucle? Ninguna diferencia

Ambos bucles imprimen exactamente lo mismo, porque el bucle solo usa el efecto (el incremento), nunca el valor de la expresión:

#include <iostream>
using namespace std;

int main() {
    for (int i = 0; i < 5; i++) cout << i << " ";
    cout << endl;
    for (int i = 0; i < 5; ++i) cout << i << " ";
    cout << endl;
    return 0;
}

¿Y cuándo cuesta la diferencia de verdad? No con int — el compilador genera código máquina idéntico. Importa con tipos clase: i++ debe conservar una copia del valor viejo para devolverla, y en un objeto grande esa copia es trabajo real. Por eso las guías de estilo de C++ dicen: prefiere ++i por hábito — nunca es más lento y a veces más rápido.

La trampa famosa: dos incrementos en una expresión

Nunca escribas cosas así, ni para «probar»:

i = i++ + ++i;   // comportamiento indefinido — no usar

Cuando una variable se modifica dos veces entre dos «puntos de secuencia» (en crudo: dentro de una misma sentencia, sin orden garantizado), el estándar se niega a decir qué ocurre. Compiladores distintos dan respuestas distintas, y los optimizadores pueden producir cualquier cosa. Un incremento por sentencia y vives en paz.

Preguntas de entrevista del tema

  1. «¿Qué imprime cout << i++?» — el valor viejo de i; después i vale uno más.
  2. «¿Cuál es más rápido, ++i o i++?» — para tipos incorporados, idéntico tras optimizar; para clases, el pre-incremento puede ahorrarse una copia.
  3. «¿Por qué está roto i = i++?» — modificar i dos veces en una sentencia sin secuenciación es comportamiento indefinido.
  4. «¿Qué es la sobrecarga de operadores aquí?» — las clases definen operator++(int) (postfijo, parámetro int mudo) y operator++() (prefijo); ese parámetro mudo es como C++ los distingue.

Práctica en el editor

  1. Predice la salida de int a = 3; int b = a++; cout << a << b; — y luego ejecútalo. (Respuesta: 4 y 3.)
  2. Lo mismo con ++a — ¿qué cambia?
  3. Pon i++ y ++i en el encabezado de un bucle for y confirma que las salidas coinciden.

Relacionado: for vs while, por qué 7/2 es 3 y las preguntas para juniors.