++c vs c++ ¿preincremento o postincremento?

Cuando creamos código, nos conviene tener muy claro lo que estamos haciendo. Muchos problemas de programación se pueden resolver de limitadas y determinadas maneras y es en estos casos donde un buen programador puede demostrar su talento. Me gustaría comentar ciertos… “truquitos”, que pueden hacer que nuestro código sea de más calidad; voy a comentar lo que en mi opinión es el mejor uso de el preincremento y el postincremento de C/C++.
Muchas de las veces que se usan los operadores de Preincremento y Postincremento (y sus equivalentes en decremento, claro) se hace en un ámbito en que no hay diferencia alguna en su uso, por ejemplo:
Anidados en bucles…
while(!File.EoF()) // EJEMPLO 1
{
BytesReaded = File.Read(&Pointer);
// Tratamos los datos leidos...
ReadCount++;
};
En líneas sueltas…
if (Numero % 2) // EJEMPLO 2
{
// Operaciones trascendentales...
}
else
{
// Calculos complejisimos...
NumeroPar++;
};
Sin embargo, aunque la mayoría de veces se usen como si fuesen equivalentes, hay diferencias importantes entre el Preincremento y el Postincremento; deberíamos comprometernos a usar la versión más adecuada a cada situación. Para conocer lo más conveniente deberemos estudiar las diferencias entre el Pre y el Post Incremento/Decremento.
La primera diferencia es, la “definición de diccionaro” del operador: Preincremento, modifica el valor previamente a cualquier operación adicional y Postincremento modifica el valor posteriormente a cualquier otra operación. Por lo tanto, en el momento de usar uno de estos operadores debemos reflexionar sobre que es lo más apropiado; escogeremos Preincremento para los casos en que necesitemos tratar el valor ya modificado y el Postincremento en los casos contrarios. Todo esto asumiendo que se hagan más operaciones en la misma línea en que usamos los operadores.
En los dos primeros ejemplos, el uso de una u otra versión aparentemente no tiene importancia ya que, no utilizamos los datos en el momento de operar con ellos (la variable afectada por el incremento está sola en la línea de código), pero en el siguiente ejemplo utilizar preincremento o postincremento puede dar resultados posiblemente inesperados:
int a, b, c; // EJEMPLO 3
a = b = c = 0;
/* c incrementa a 1 ANTES de pasarle el valor a a.
a obtiene el valor 1 */
a = ++c;
/* c incrementa a 2 DESPUES de pasarle el valor a b.
b obtiene el valor 1 */
b = c++;
Por lo tanto, se debe tener cuidado usando los Incrementos y Decrementos.
La segunda diferencia corresponde a la forma en que trabaja cada operador. Vamos a hechar un vistazo a sus funciones de sobrecarga:
// Preincremento
tipo operator++()
{
*this = *this + 1;
return *this;
};
// Postincremento
tipo operator++(int)
{
tipo temp = *this;
*this = *this + 1;
return temp;
}
Estos serían los códigos de un preincremento y postincremente genéricos de tipo “tipo”; como podemos ver, al usar el preincremento, en primer lugar se incrementa el valor del objeto, y seguidamente se devuelve su valor. Sin embargo para el postincremento se guarda el valor anterior en una variable temporal, y después de incrementar el valor, devolvemos el valor guardado anteriormente. Asi que, el preincremento hace una operación menos.
Ahora que hemos analizado las diferencias, tenemos criterio para afirmar:
- El postincremento debe usarse con cuidado, pues a veces resulta engañoso (Ejemplo 3).
- Cuando no haya diferencia alguna entre usar pre/post incremento/decremento es mejor usar el Preincremento, ya que hace una operación menos (En los Ejemplos 1 y 2 se debería haber usado Preincremento).
¡Tenedlo en cuenta en vuestros códigos! ^_^
8 comentarios »
Deja un comentario
-
Archivos
- Octubre de 2009 (1)
- Agosto de 2009 (11)
- Febrero de 2009 (2)
- Diciembre de 2008 (2)
- Noviembre de 2008 (2)
- Octubre de 2008 (1)
- Septiembre de 2008 (4)
- Agosto de 2008 (2)
- Febrero de 2008 (1)
- Enero de 2008 (7)
- Diciembre de 2007 (3)
- Noviembre de 2007 (1)
-
Categorías
-
RSS
Subscripciones RSS
RSS de los Comentarios
Como no, ya estaba tardando yo en leer un post de pre y postincrementos en este blog!!!
La verdad, muy educativo el post, y muy bien explicado con sus ejemplos y demás. La verdad es que posts de estos son los que hacen que te preguntes ¿en realidad programo bien, o mi codigo es escoria total?.
En fin, un saludete y a seguir con la genial iniciativa.
Pues el próximo artículo sobre programación es de bucles.
¡Preparate! :P
Excelente explicaciòn.
Gracias.
Talvez alguien se anime a explicar el orden en que se resolveria el siguiente ejemplo:
Si,
int a=10, b=100, c=30, d=1, e=54;
int m[10]={10,20,30,40,50,60,70,80,90,100};
int *p=m[3], *q=m[6];
Resolver:
a + m[c/a] + b– * m[1]/*q + 10 + a–;
No logro comprender como hacer con los postdecrementos (b– y a–), les resto uno y opero ò no lo hago?
Agradeceria cualquier ayuda, sigo un tutorial que baje por internet y se me hace algo dificil.
Gracias.
Ok, ya resolvi el problema que coloque anteriormente , el resultado es 98.
Ahora tengo un nuevo ejercicio con los mismos datos anteriores que me causa mucho problema talvez pueda alguien explicar la soluciòn.
Problema:
q[-3] + q[2];
Saludos…
Excelencia! :)
Otro aspecto importante de que el pre retorne el mismo objeto incrementado y el post una copia es que permite cosas como:
int a = 0;
++++a;
y prohive:
a++++;
++num++; // Los post suelen tener mas peso que los pre
El que el retorno sea una constante nos va a prohibir llamar a métodos no constantes en los objetos constantes de retorno(aunque a algunos compiladores se le vaya la pinza con estas cosas, como por ej VS2008).
Tampoco podremos pasar una constante de retorno a una función que espere una referencia no constante.
En fin, tonterias, pero hay que tenerlas en cuenta.
Buen blog… entre por casualidad.
Un Saludo, bytess
todo bien