smart punteros inteligentes c++ c++11 shared-ptr smart-pointers auto-ptr

punteros - smart pointers c++



EliminaciĆ³n de puntero a tipo incompleto y punteros inteligentes (1)

Un shared_ptr se puede declarar con un tipo incompleto, sí. No es necesario que el tipo esté completo hasta que lo inicialice o restablezca.

Cuando inicializa o restablece un shared_ptr para que apunte a un nuevo objeto, crea un "eliminador" que se puede usar para destruir el objeto. Por ejemplo, considere lo siguiente:

// somewhere where A is incomplete: std::shared_ptr<class A> p; // define A class A { /* ... */ }; p.reset(new A());

Cuando llama al reset , A está completo porque está creando una instancia del mismo utilizando new . La función de reset crea y almacena internamente un eliminador que se utilizará para destruir el objeto mediante la delete . Debido a que A está completa aquí, esa delete hará lo correcto.

Al hacer esto, shared_ptr no requiere que A esté completo cuando se shared_ptr<A> ; solo requiere que A esté completo cuando se shared_ptr constructor shared_ptr que toma un puntero en bruto o cuando se llama a reset con un puntero en bruto.

Tenga en cuenta que si A no está completo cuando realiza una de esas dos cosas, shared_ptr no hará lo correcto y el comportamiento no está definido (esto se explica en la documentación de boost::shared_ptr , que es probablemente el mejor recurso para aprender cómo utilizar shared_ptr correctamente, independientemente de la versión de shared_ptr que esté utilizando (Boost, TR1, C ++ 0x, etc.)).

Sin embargo, siempre que siga las mejores prácticas de uso para shared_ptr --notably, si siempre inicializa y restablece un shared_ptr directamente con un puntero resultante de una llamada a un new no tendrá que preocuparse por violar esta regla.

Esta funcionalidad no es gratuita: shared_ptr tiene que crear y almacenar un puntero al functor deleter; Por lo general, esto se hace almacenando el eliminador como parte del bloque que almacena los recuentos de referencias fuertes y débiles o teniendo un puntero como parte de ese bloque que apunta al eliminador (ya que puede proporcionar su propio eliminador).

auto_ptr (y unique_ptr también) está diseñado para estar libre de gastos generales: se supone que las operaciones en él son tan eficientes como usar un puntero tonto. Por lo tanto, auto_ptr no tiene esta funcionalidad.

Al intentar usar un auto_ptr con un tipo que fue declarado con declaración de reenvío, como esto:

class A; ... std::auto_ptr<A> a;

no se llama al destructor de A (aparentemente, porque auto_ptr delete internamente s el puntero subyacente y no se puede llamar al destructor para un tipo incompleto).

Sin embargo, el mismo código funciona bien y se llama al destructor cuando se usa std::shared_ptr lugar de std::auto_ptr . ¿Cómo se puede explicar eso?