#include <stdlib.h> struct Persona { }; int main() { Persona* a = malloc(sizeof(Persona)); free(a); return 0; }
Un ejemplo equivalente en C++:
class Persona { }; int main() { Persona* a = new Persona(); delete a; return 0; }
Por cada malloc existe un free (al menos que use reallocs), y por cada new existe un delete (y por cada new[] un delete[]).
¿Existe una forma por la cual C++ se "entere" que ya no quiero usar un puntero? La respuesta es: No, no existe. C++ no tiene un garbage collector. Pero existen clases que pueden ayudarnos, como el viejo y tan poco querido auto_ptr, o los mejorados unique_ptr, shared_ptr y weak_ptr del nuevo estándar de C++0x (o el TR1).
Un shared pointer es una clase que se encarga de guardar un puntero a un objeto (o tipo de dato), y cuenta la cantidad de referencias que se están haciendo a dicho objeto (es decir, la cantidad de shared pointers que apuntan al mismo objeto). El último shared pointer que se destruya (cuando las referencias llegan a cero), será el encargado de borrar el objeto apuntado (mediante un simple delete).
Un ejemplo:
#include <iostream> #include <memory> // Aquí debería estar shared_ptr<> (GCC 4.4) using namespace std; class Persona { int n; public: Persona(int n) : n(n) { cout << "Nace la persona " << n << "\n"; } ~Persona() { cout << "Muere la persona " << n << "\n"; } static shared_ptr<Persona> Crear(int n) { return shared_ptr<Persona>(new Persona(n)); } }; int main() { shared_ptr<Persona> a(new Persona(1)); shared_ptr<Persona> b = Persona::Crear(2); shared_ptr<Persona> c; cout << "--- Aquí ambas personas existen ---\n"; c = a; // Aquí c apunta a la persona 1 b = c; // Ahora b apuntará a la persona 1 (la persona 2 muere porque // ya no existen referencias a ella) cout << "--- Aquí la persona 2 ya no existe ---\n"; return 0; } // Aquí muere la persona 1 (a, b, c apuntaban a ella)La salida del anterior programa es esta:
Nace la persona 1 Nace la persona 2 --- Aquí ambas personas existen --- Muere la persona 2 --- Aquí la persona 2 ya no existe --- Muere la persona 1Como puede ver, en el anterior programa se llama sólo dos veces a "new Persona" y dos veces al destructor ~Persona. No debemos preocuparnos por usar "delete", el shared_ptr<> hace todo por nosotros.
¿Cómo hago para que la clase shared_ptr funcione en VS2008 SP1 Express? Debe definir _HAS_TR1 antes de incluir el archivo <memory>. Ejemplo:
#ifdef _MSC_VER // Si estamos usando el compilador de Microsoft #define _HAS_TR1 1 // Esto hará que se incluyan las clases del TR1 (std::tr1) #endif #include <iostream> #include <memory> using namespace std; #ifdef _MSC_VER using namespace std::tr1; // para tener shared_ptr<> disponible #endif // Resto del ejemplo...