A Coder’s Corner

Blog de tecnologia y programación

Smart Pointers

Posted by gfaraj on May 8, 2007

Un “smart pointer” es un pointer que sabe cuando debe borrarse y lo hace. Usarlos en vez de punteros crudos podria salvarles mucho tiempo de debugging, pero usarlos mal les podria extender ese tiempo. Los que estan implementados en Boost estan bien hechos y son thread-safe. Les recomendaria usar esos en vez de implementar una version propia, ya que estos son probados exhaustivamente.

Voy a hablar sobre dos tipos de smart pointers: el scoped pointer y el shared pointer. El primero no se puede copiar; como dice su nombre, se usa en un “scope.”

{
    boost::scoped_ptr<MiClase> ptr1(new MiClase);
    ptr1->foo();

    {
        boost::scoped_ptr<int> ptr2(new int);
        *ptr2 = 10;
        // ptr2 se destruye aqui
    }

    // ptr1 se destruye aqui
}

A simple vista, se puede observar la utilidad de esta clase. No nos tenemos que preocupar por llamar delete despues de usar el puntero. Pero, también tiene una caracteristica muy buena que talvez sea mas dificil de ver. Si ptr1->foo(); tira un exception, este codigo no produciria un leak de memoria ya que el destructor de ptr1 se llamara y destruira el puntero. Con punteros crudos habria que poner un try-catch y borrar el puntero en el catch para que el codigo sea igual de correcto.

El otro tipo de smart pointers que voy a presentar es el shared pointer. Este si se puede copiar, y lo que hace es que mantiene un “reference count” de cuantas veces ha sido copiado. Se borra el puntero hasta que la ultima copia se haya destruido (o sea cuando el count llega a 0).

{
    boost::shared_ptr<MiClase> ptr1(new MiClase);
    ptr1->foo();

    {
        boost::shared_ptr<MiClase> ptr2(ptr1);
        ptr2->foo();
        // decrementa el reference count
    }

    // decrementa el reference count
    // borra el puntero
}

La utilidad que agrega esta clase a la del scoped pointer es que esta si la podemos copiar. Si se ocupa que un puntero sea compartido entre varias clases o modulos, usar esta clase es ideal. La razon es que el shared_ptr no va a dejar que el puntero muera hasta que todas las copias se hayan destruido, asi que es mas seguro. Claro, hay que tener cuidado y usar correctamente esta clase.

{
    MiClase* puntero = new MiClase;

    boost::shared_ptr<MiClase> ptr1(puntero);
    boost::shared_ptr<MiClase> ptr2(puntero);

    // boom! el mismo puntero se borro dos veces
}

Tambien existe el problema de la referencia circular. Prueben el siguiente codigo y veran que ningun destructor se ejecuta.

struct B;

struct A
{
    ~A() { std::cout << "~A()"; }
    boost::shared_ptr<B> ptrB;
};

struct B
{
    ~B() { std::cout << "~B()"; }
    boost::shared_ptr<A> ptrA;
};

int main()
{
    boost::shared_ptr<A> ptr(new A);
    ptr->ptrB.reset(new B);
    ptr->ptrB->ptrA = ptr;

    // ninguno se destruye
}

Usandolas correctamente, estas clases nos pueden hacer la vida mucho más facil. El codigo producido al usar estas clases es más robusto y seguro.

One Response to “Smart Pointers”

  1. hoper said

    cool! me voy a tener que dar mis vueltesitas por aquí, hay varia mañanas en c++ que no me sabía🙂 a molestar maestros con nuevas keywords, saludos.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: