#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>La salida del anterior programa es esta:
#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)
Nace 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.
Nace la persona 2
--- Aquí ambas personas existen ---
Muere la persona 2
--- Aquí la persona 2 ya no existe ---
Muere la persona 1
¿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...