c++ - ¿Cuándo usarías un std:: auto_ptr en lugar de boost:: shared_ptr?
stl shared-ptr (3)
Nos hemos movido a usar boost::shared_ptr
en todo nuestro código, sin embargo, todavía tenemos algunos casos aislados en los que usamos std::auto_ptr
, incluidas las clases singleton:
template < typename TYPE >
class SharedSingleton
{
public:
static TYPE& Instance()
{
if (_ptrInstance.get() == NULL)
_ptrInstance.reset(new TYPE);
return *_ptrInstance;
}
protected:
SharedSingleton() {};
private:
static std::auto_ptr < TYPE > _ptrInstance;
};
Me han dicho que hay una muy buena razón por la que esto no se ha hecho un shared_ptr
, pero por mi vida no puedo entender por qué. Sé que auto_ptr
eventualmente se marcará como depreciado en el siguiente estándar, así que me gustaría saber qué / cómo puedo reemplazar esta implementación .
Además, ¿existen otras razones por las que consideraría usar un auto_ptr
lugar de shared_ptr
? ¿Y ve algún problema para pasar a shared_ptr en el futuro?
Editar:
- Entonces, en respuesta a "¿puedo reemplazar de forma segura a
auto_ptr
conshared_ptr
en el código anterior", la respuesta es sí? Sin embargo, recibiré un pequeño impacto de rendimiento. - Cuando
auto_ptr
finalmente se marca como depreciado y nos movemos astd::shared_ptr
, tendremos que probar exhaustivamente nuestro código para asegurarnos de que cumplimos con la semántica de propiedad diferente.
Otros han respondido por qué este código utiliza un auto_ptr
lugar de un shared_ptr
. Para abordar sus otras preguntas:
¿Qué / cómo puedo reemplazar esta implementación?
Use boost::scoped_ptr
o unique_ptr
(disponible tanto en Boost como en el nuevo estándar de C ++). Tanto scoped_ptr
como unique_ptr
proporcionan una propiedad estricta (y no tienen gastos generales de conteo de referencias), y evitan la sorprendente semántica de eliminación en copia de auto_ptr
.
Además, ¿existen otras razones por las que consideraría usar un auto_ptr
lugar de shared_ptr
? ¿Y ve algún problema para pasar a shared_ptr
en el futuro?
Personalmente, no usaría un auto_ptr
. Eliminar-en-copiar es demasiado no intuitivo. Herb Sutter parece estar de acuerdo . Cambiar a scoped_ptr
, unique_ptr
, o shared_ptr
debería ofrecer problemas. Específicamente, shared_ptr
debe ser un reemplazo shared_ptr
si no le importa la sobrecarga de conteo de referencia. scoped_ptr
es un reemplazo scoped_ptr
si no está usando las capacidades de transferencia de propiedad de auto_ptr
. Si está usando la transferencia de propiedad, unique_ptr
es casi un reemplazo unique_ptr
, excepto que en su lugar debe llamar explícitamente a move
para transferir la propiedad. Vea here para un ejemplo.
auto_ptr es el único tipo de puntero inteligente que uso. Lo uso porque no uso Boost, y porque generalmente prefiero que mis clases orientadas a negocios / aplicaciones definan explícitamente la orden y la semántica de eliminación, en lugar de depender de colecciones de punteros inteligentes o individuales.
auto_ptr
y shared_ptr
resuelven problemas completamente diferentes. Uno no reemplaza al otro.
auto_ptr
es una envoltura delgada alrededor de los punteros para implementar la semántica RAII , de modo que los recursos siempre se liberan, incluso cuando se enfrentan a excepciones. auto_ptr
no realiza ningún recuento de referencias ni nada similar, no hace que los punteros múltiples apunten al mismo objeto al crear copias. De hecho, es muy diferente. auto_ptr
es una de las pocas clases en las que el operador de asignación modifica el objeto de origen . Considere este enchufe descarado de la página wikipedia de auto_ptr :
int *i = new int;
auto_ptr<int> x(i);
auto_ptr<int> y;
y = x;
cout << x.get() << endl; // Print NULL
cout << y.get() << endl; // Print non-NULL address i
Note como ejecutando
y = x;
modifica no solo y también x.
La plantilla boost::shared_ptr
facilita el manejo de múltiples punteros hacia el mismo objeto, y el objeto solo se elimina después de que la última referencia a él se haya salido del alcance. Esta función no es útil en su escenario, que (intenta) implementar un Singleton . En su escenario, siempre hay 0 referencias a 1 referencia al único objeto de la clase, si corresponde.
En esencia, los objetos auto_ptr
y shared_ptr
tienen una semántica completamente diferente (por eso no puede usar el primero en contenedores, pero hacerlo con el último está bien), y espero que tenga buenas pruebas para detectar las regresiones que introdujo al transportar su código. : -}