Página principal
Artículos y trucos
Catálogo de productos
Ejemplos y descargas
Mis libros
Cursos de formación
Investigación y desarrollo
Libros recomendados
Mis páginas favoritas
Acerca del autor
 
En colaboración con Amazon
 
Intuitive Sight

El operador delete y el método Free

Como la memoria RAM tiene los precios por los suelos, ya nadie se preocupa de optimizar sus programas para que no ocupen espacio innecesario ... menos ciertos idiotas (como el que escribe estas líneas) que creen que no sólo es importante el resultado final del proceso de programación (la aplicación) sino también el estilo con el cuál pasamos por el mismo. No se trata de ir mirando con lupa cada instrucción, ni de dormir con un manual de profiling como almohada. Pero muchas veces programamos descuidadamente, y utilizamos ciertas instrucciones que son más lentas o voluminosas que algunas alternativas. Vale, si no conocemos la existencia de estas alternativas no estamos cometiendo "pecado mortal"; pero en cualquier otro caso estamos condenando nuestra alma al infierno. El infierno es una sala de programación calurosa, con un servidor de Windows NT 3.51, ordenadores clónicos que fallan cada dos por tres y un capataz de corbata azotando a los condenados para que terminen los arreglos a una aplicación escrita en Visual Basic escrita por terceros...

Este truco está dirigido a los programadores de C++ Builder. Todos conocemos que en la VCL los objetos de clases descendientes de TObject se destruyen mediante un destructor virtual programado en Pascal cuyo nombre es Destroy. Los destructores de Object Pascal no verifican si el puntero que reciben tiene algún objeto asociado, o si simplemente contiene la constante nil. Pero la misma clase TObject implementa el método Free, que sí comprueba el valor del puntero antes de pasárselo al destructor:

procedure TObject.Free;
begin
   if Self <> nil then Destroy;
end;

Ahora vamos de vuelta a C++ Builder. Es bien sabido que la verificación de la nulidad de un puntero es parte de la semántica del operador delete; en realidad, C++ nunca permite llamar explícitamente a un destructor, como sucede en Object Pascal. El operador delete, como se puede comprobar fácilmente, verifica que el puntero que se le pasa no sea nulo antes de destruir el objeto asociado. Así que en C++ Builder parece que Free está condenado a cubrirse de polvo en algún rincón perdido de nuestras neuronas.

¿Está seguro? Yo pensaba lo mismo, hasta que la curiosidad me dio por averiguar cómo se implementaba una llamada a delete. Utilizando la ventana CPU del depurador de C++ Builder 4, comparé las implementaciones de una destrucción de un objeto dinámico (como todos los de la VCL) en cuatro variantes diferentes:

  1. La variable de puntero era global. Destrucción con delete.
  2. Variable de puntero global. Destrucción con Free.
  3. Variable de puntero local. Destrucción con delete.
  4. Variable de puntero local. Destrucción con Free.

Por ejemplo, para el primer caso utilicé el siguiente código:

void __fastcall TForm2::Button1Click(TObject *Sender)
{
   // Form2 es una variable global
   Form2 = new TForm2(0);
   Form2->ShowModal();
   delete Form2;
   // La alternativa sería: Form2->Free();
}

Bien, dejemos que los números hablen por nosotros. Estos son los resultados, que se refieren al tamaño en bytes de la operación que destruye al objeto:

 Free delete 
Variable global  13 bytes51 bytes
Variable local  8 bytes46 bytes

Como se puede ver, en cada llamada a delete sobre un objeto de la VCL que sustituyamos por un Free estaremos ahorrando 38 bytes. Ya sé que 38 bytes no es nada, pero sume todas las veces que llama a delete desde su aplicación y saque cuentas. Y, como decía al principio, ¿por qué utilizar inútilmente la peor alternativa, una vez que conocemos una mejor?