¿Existe una diferencia de rendimiento entre i++ y ++i en C++?

Resuelto Mark Harrison asked hace 16 años • 20 respuestas

Tenemos la pregunta: ¿existe una diferencia de rendimiento entre i++y ++i en C ?

¿Cuál es la respuesta para C++?

Mark Harrison avatar Aug 24 '08 14:08 Mark Harrison
Aceptado

[Resumen ejecutivo: utilícelo ++isi no tiene un motivo específico para usarlo i++].

Para C++, la respuesta es un poco más complicada.

Si ies un tipo simple (no una instancia de una clase C++), entonces la respuesta dada para C ("No, no hay diferencia de rendimiento") es válida, ya que el compilador está generando el código.

Sin embargo, si ies una instancia de una clase C++, entonces i++y ++iestán realizando llamadas a una de las operator++funciones. Aquí hay un par estándar de estas funciones:

Foo& Foo::operator++()   // called for ++i
{
    this->data += 1;
    return *this;
}

Foo Foo::operator++(int ignored_dummy_value)   // called for i++
{
    Foo tmp(*this);   // variable "tmp" cannot be optimized away by the compiler
    ++(*this);
    return tmp;
}

Dado que el compilador no genera código, sino que simplemente llama a una operator++función, no hay forma de optimizar la tmpvariable y su constructor de copia asociado. Si el constructor de copias es caro, esto puede tener un impacto significativo en el rendimiento.

Mark Harrison avatar Aug 24 '2008 07:08 Mark Harrison

Sí. Hay.

El operador ++ puede estar definido o no como una función. Para los tipos primitivos (int, double, ...) los operadores están integrados, por lo que el compilador probablemente podrá optimizar su código. Pero en el caso de un objeto que define el operador ++ la cosa es diferente.

La función operador++(int) debe crear una copia. Esto se debe a que se espera que postfix ++ devuelva un valor diferente al que contiene: debe mantener su valor en una variable temporal, incrementar su valor y devolver la temperatura. En el caso del operador++(), prefijo ++, no es necesario crear una copia: el objeto puede incrementarse y luego simplemente regresar.

He aquí una ilustración del punto:

struct C
{
    C& operator++();      // prefix
    C  operator++(int);   // postfix

private:

    int i_;
};

C& C::operator++()
{
    ++i_;
    return *this;   // self, no copy created
}

C C::operator++(int ignored_dummy_value)
{
    C t(*this);
    ++(*this);
    return t;   // return a copy
}

Cada vez que llamas a operator++(int) debes crear una copia y el compilador no puede hacer nada al respecto. Cuando tenga la opción, utilice operator++(); De esta manera no guardas una copia. Puede ser significativo en el caso de muchos incrementos (¿bucle grande?) y/o objetos grandes.

wilhelmtell avatar Aug 24 '2008 07:08 wilhelmtell