A shared_ptr
pueden declararse 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 apuntar a un nuevo objeto, crea un "eliminador" que puede usarse 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 se llama a reset
, A
es completa porque va a crear una instancia del mismo utilizando new
. La función reset
crea y almacena internamente un eliminador que se usará para destruir el objeto usando delete
. Como A
se completa aquí, delete
hará lo correcto.
Al hacer esto, shared_ptr
no requiere que A
se complete cuando se declare shared_ptr<A>
; solo requiere que se complete A
cuando se invoca el constructor shared_ptr
que toma un puntero sin formato o cuando se llama al reset
con un puntero sin formato.
Tenga en cuenta que si no A
es completa cuando haces una de esas dos cosas, shared_ptr
no vamos a hacer lo correcto y el comportamiento no está definido (esto se explica en the documentation for boost::shared_ptr
, que es probablemente el mejor recurso para el aprendizaje cómo usar shared_ptr
correctamente, independientemente de qué versión de shared_ptr
esté usando (Boost, TR1, C++ 0x, etc.)).
Sin embargo, siempre y cuando se siga siempre las mejores prácticas de uso de shared_ptr
--notably, si siempre inicializar y restablece una shared_ptr
directamente con un puntero como resultado de una llamada a new
--usted no tendrá que preocuparse violando esta regla.
Esta funcionalidad no es gratuita: shared_ptr
tiene que crear y almacenar un puntero al funtor de borrado; por lo general, esto se hace almacenando el eliminador como parte del bloque que almacena los recuentos de referencia 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 no tener gastos generales: se supone que las operaciones en él son igual de eficientes que usar un puntero tonto. Por lo tanto, auto_ptr
no tiene esta funcionalidad.
+1! Gracias por la explicación exhaustiva. –
Aquí hay un resumen de los requisitos de integridad para unique_ptr y shared_ptr: http://home.roadrunner.com/~hinnant/incomplete.html –
Durante una hora de material altamente entretenido en shared_ptr, consulte [STL en STL] (http: // channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-1-of-n). También vale la pena mencionar 'std :: make_shared'. –