Pregunta

He estado reflexionando sobre el uso de unique_ptr vs shared_ptr vs own_solution.He descartado este último porque es casi seguro que me equivoque, pero tengo un problema con ambos. unique_ptr y shared_ptr en que ninguno captura precisamente lo que quiero.Quiero crear un administrador de recursos que sea propietario explícito de un recurso; sin embargo, me gustaría que el administrador de recursos también entregue referencias al recurso.

si uso unique_ptr en el administrador de recursos y entregar sugerencias en bruto, existe la posibilidad de que puedan escapar a otro lugar (aunque esto iría en contra del "contrato" de clase, supongo).si uso shared_ptr y repartir weak_ptr, no hay nada que impida que quien llama convierta el weak_ptr a un shared_ptr y almacenarlo, creando así potencialmente un ciclo o, peor aún, un recurso que viva más allá de la vida útil del administrador de recursos.Entonces supongo que lo que estoy buscando es un deferencable weak_ptr que no se puede convertir en shared_ptr.

¿O simplemente estoy buscando hacer cumplir el contrato con algunos comentarios fuertemente redactados en el código?

Gracias por cualquier idea que puedas tener sobre esto.

¿Fue útil?

Solución

Punteros inteligentes como shared_ptr y unique_ptr son unas buenas herramientas cuando tienes poseer punteros.
Pero para los punteros que no son propietarios, es decir observando punteros, usar un puntero sin formato está bien.

En su diseño, creo que el administrador de recursos es el único "propietario" de los recursos, por lo que simplemente podría tener algún tipo de puntero inteligente. adentro el administrador de recursos.Por ejemplo, el administrador de recursos puede tener un std::vector<std::unique_ptr<Resource>> como miembro de datos, o incluso una forma más simple std::vector<Resource> si tu Resource La clase está diseñada para poder almacenarse correctamente en un std::vector.

Luego, el administrador de recursos puede proporcionar al exterior solo punteros de observación que no son propietarios, y los punteros sin formato (o referencias de C++) están bien para este caso.

Por supuesto, es importante que la vida útil del administrador de recursos supere la de los "clientes de recursos".

Otros consejos

Al final, no se puede obligar a nadie a escuchar.Pregunte en Microsoft, Apple o cualquier desarrollador de bibliotecas de código abierto, todos conocen esa canción.Un comentario con las palabras y lugares correctos es tu mejor opción.

Evite crear su propia clase de puntero inteligente, ya que dificulta la composición y reduce la legibilidad.Como último recurso, intente buscar en boost o en cualquier marco con el que su código ya tenga que funcionar.

Si no tiene propietarios, estos pueden ser elegibles para ser propietarios weak_ptrs o (si se garantiza que seguirá siendo válido mientras dure) punteros sin formato.
Si utiliza shared_ptrs internamente (¿por qué debería hacerlo?), es mejor proporcionar weak_ptr y consejos crudos.

Todos esos consejos inteligentes denotan explícitamente una política de propiedad.Los punteros sin procesar denotan ninguno o no propietario.

  • auto_ptr:No lo use, está en desuso y tiene demasiadas trampas incluso para los más cautelosos.
  • unique_ptr:Propiedad exclusiva.
  • shared_ptr:Propiedad compartida
  • weak_ptr:Sin propiedad, es posible que se eliminen a tus espaldas.
  • puntero crudo
    • Explícitamente sin propiedad con una vida útil mayor garantizada
    • o gestión manual de la propiedad.

Así que supongo que lo que estoy buscando es un débil_ptr aplazable que no se pueda convertir en un shared_ptr.

Podrías repartir tu pequeña clase de ayuda:

template<typename T>
class NonConvertibleWeakPtr
{
public:
   NonConvertibleWeakPtr(const std::shared_ptr<T>& p) : p_(p) {}
   ... // other constructors / assignment operators
   bool expired() const { return p_.expired(); }
   T* operator->() const { return get(); }
   T& operator*() const { return *get(); }
private:
   T* get() const { return p_.lock().get(); }
private:
   std::weak_ptr<T> p_;
};

Esto es ligeramente mejor que un puntero sin formato, porque puede verificar si su puntero aún es válido.

Uso de ejemplo:

std::shared_ptr<int> sp = std::make_shared<int>(5);
{
    NonConvertibleWeakPtr<int> wp(sp);
    if(!wp.expired()) {
        std::cout << *wp << std::endl;
    }
}

Sin embargo, un usuario aún puede hacer un mal uso, por ejemplo con std::shared_ptr<T> blah(&(*wp));, pero se necesita un poco más de energía criminal.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top