existentes - for auto c++
unique_ptr<> v shared_ptr<> con respecto a la política de destrucción (1)
Me he estado enseñando a mí mismo los punteros inteligentes que son parte de C ++ 0x y encontré algo que me parece inconsistente. Específicamente, cómo se maneja la política de destrucción de unique_ptr <> y shared_ptr <>.
Para unique_ptr <>, puede especializar std :: default_delete <> y, a partir de ese momento, a menos que solicite explícitamente una política de destrucción diferente, se utilizará el nuevo valor predeterminado.
Considera lo siguiente:
struct some_c_type;
some_c_type *construct_some_c_type();
void destruct_some_c_type(some_c_type *);
namespace std {
template <> struct default_delete<some_c_type> {
void operator()(some_c_type *ptr) {
destruct_some_c_type(ptr);
}
};
}
Ahora, una vez que esté en su lugar, unique_ptr <> usará la política de destrucción apropiada de manera predeterminada:
// Because of the specialization, this will use destruct_some_c_type
std::unique_ptr<some_c_type> var(construct_some_c_type());
Ahora compare esto con shared_ptr <>. Con shared_ptr <>, debe solicitar explícitamente la política de destrucción adecuada o, de forma predeterminada, usar la eliminación del operador:
// error, will use operator delete
std::shared_ptr<some_c_type> var(construct_some_c_type());
// correct, must explicitly request the destruction policy
std::shared_ptr<some_c_type> var(construct_some_c_type(),
std::default_delete<some_c_type>());
Dos preguntas.
- ¿Estoy seguro de que shared_ptr <> requiere que se especifique la política de destrucción cada vez que se use o me falta algo?
- Si no me falta algo, ¿alguna idea de por qué los dos son diferentes?
PD La razón por la que me importa esto es que mi empresa hace muchas programaciones mixtas en C y C ++. El código de C ++ a menudo necesita usar objetos de estilo C, por lo que la facilidad de especificar una política de destrucción predeterminada diferente es muy importante para mí.
Creo que la pregunta se reduce a por qué std :: shared_ptr no puede tener un eliminador asociado (en cuyo caso solo se llama delete
) en lugar de construir un std::default_delete
de forma predeterminada. (No tengo idea. Si la intención era que default_delete
es para especializarse, uno esperaría que lo use shared_ptr
).
De lo contrario, hay compensaciones.
Es mejor tener menos argumentos de plantilla. La referencia de Boost menciona que esto permite que una fábrica cambie el esquema de asignación sin que el cambio afecte al usuario de la fábrica.
Un unique_ptr
por otro lado se supone que es muy ligero. ¿Cómo almacenaría el eliminador con una sobrecarga de espacio cero (en el caso de un functor sin miembros) si no formara parte del tipo (GCC usa la tupla, donde los objetos sin miembros no ocupan espacio en la memoria)?
Subjetivamente, creo que preferiría:
unique_ptr<FILE, FCloser> f(fopen(x, y));
a
unique_ptr<FILE> f(fopen(x, y)); //default_delete<FILE> has been specialized
En el primer caso no hay nada que adivinar. Si el recurso no proviene de new
o new[]
, se debe dar un borrado explícitamente.