Un ejemplo. Teniendo la siguiente clase Acumulador:
#include <cstdio>
class Acumulador {
int v;
public:
Acumulador() { v = 0; }
~Acumulador() { std::printf("%d\n", v); }
void acumular(int x) { v += x; }
};
Un código como el siguiente:{
Acumulador acum;
acum.acumular(2);
acum.acumular(4);
acum.acumular(10);
}
Al compilarlo (optimizándolo), el código equivale a exactamente esto:{
int v = 0;
v += 2;
v += 4;
v += 10;
std::printf("%d\n", v);
}
La clase Acumulador ya no existe. Obtenemos el código más óptimo posible: sin llamadas a la función "acumular", ni ningún byte extra de memoria (Acumulador ocupa lo mismo de memoria que ocupa un "int").Este ejemplo no ayuda a ver grandes ventajas, pero si el constructor y el destructor hacen tareas complicadas, y las funciones miembros también, el resultado puede llevarnos a dos puntos:
- Nos abstrae de la complejidad de la implementación (e.j. para qué quiero saber cómo se acumula si sólo quiero acumular)
- Obtenemos código tan óptimo como si no hubiéramos usado la abstracción (e.j. las operaciones se acercan al hardware tanto como sea posible).

3 comments:
Hay que tener en cuenta que el optimizador realiza un balance entre: ¿qué me conviene hacer? ¿hago la llamada a una función? ¿o pongo el código de la función acá mismo?
Existe algo llamado "function call overhead", que es "la cantidad de cosas que tengo que hacer para llamar una función". Si esta cantidad de "cosas" es mayor al código mismo de la función, es bastante razonable colocar el mismo código de la función "en línea" (inline).
C++ nos deja usar la abstracción apuntando a que sea transparente, (como debe ser), aunque no siempre le es fácil (o posible).
Aquí da vueltas la palabra "minimo". Existe uno o varios algoritmos expresados en instrucciones del micro (ASM) que son mínimos en algún sentido (tiempo de ejecución, memoria utilizada, stack utilizado..) que cualquier otra versión para la misma tarea, sería mayor.
Esto me recuerda a cuestiones matemáticas símples como los sistemas de ecuaciones lineales donde con 1 ecuación y 3 incógnitas no obtengo solución única, si tengo 3 y 3, tengo chances de encontrarla, y si hubiera 3 ecuaciones y 1 incógnita, ya sobran datos, el sistema puede ser incompatible o redundante.
http://es.wikipedia.org/wiki/Sistema_de_ecuaciones_lineales
Saber eso, nos hace sospechar (cada vez que estamos frente a un algoritmo) si ¿no será redundante tanto código?, ¿no habrá ecuaciones de más? y sabemos que si hay de más, pueden ser redundante (el usuario "solo" padecera lentitud y tamaño), o en el peor de los casos, incompatible consigo mismo (el usuario recordará a nuestra madre y abuela).
En un punto del espacio (de memoria) o del tiempo (de ejecución) esta incompatibilidad puede salir a la luz disfrazada de BUG. (El señor Dijkstra mencionó que habría que llamarle ERRORES y no BUGS, porque dejaba más en claro quién era el responsable de que estén ahí, la palabra BUG hacía parecer que sólos se metían en el código http://en.wikipedia.org/wiki/Edsger_W._Dijkstra)
De todas formas me parece que la responsabilidad de estos logros (encontrar mínimos, o cercanos a eso) debe estar compartida entre el lenguaje (que cuide al programador de la redundancia) y el programador (que no sea tan vago jaja)
En fin cosas importantes, usuales e impresindibles a tener en cuenta cuando se programan microcontroladores con muy escasos recursos de memoria y procesador, ¿Qué hace un programador de PC que podría estar jugando con frameworks de Gigas considerando estas cosas? Respuesta: se gana el respeto y saludo de quienes estamos en las trinchera de los bits
Publicar un comentario en la entrada