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?