Actualmente estoy tratando de aprender a usar punteros inteligentes. Sin embargo, mientras hacía algunos experimentos, descubrí la siguiente situación para la que no pude encontrar una solución satisfactoria:
Imagina que tienes un objeto de clase A que es padre de un objeto de clase B (el hijo), pero ambos deberían conocerse:
class A;
class B;
class A
{
public:
void addChild(std::shared_ptr<B> child)
{
children->push_back(child);
// How to do pass the pointer correctly?
// child->setParent(this); // wrong
// ^^^^
}
private:
std::list<std::shared_ptr<B>> children;
};
class B
{
public:
setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
};
private:
std::shared_ptr<A> parent;
};
La pregunta es ¿cómo puede un objeto de clase A pasar un std::shared_ptr
de sí mismo ( this
) a su hijo?
Hay soluciones para los punteros compartidos de Boost ( obteniendo un boost::shared_ptr
parathis
), pero ¿cómo manejar esto usando los std::
punteros inteligentes?
c++
this
shared-ptr
this-pointer
Ícaro
fuente
fuente
Respuestas:
Hay
std::enable_shared_from_this
solo para este propósito. Usted hereda de él y puede llamar.shared_from_this()
desde dentro de la clase. Además, aquí está creando dependencias circulares que pueden provocar pérdidas de recursos. Eso se puede resolver con el uso destd::weak_ptr
. Entonces, su código podría verse así (asumiendo que los niños dependen de la existencia del padre y no al revés):Sin embargo, tenga en cuenta que la llamada
.shared_from_this()
requiere quethis
sea propiedad destd::shared_ptr
en el punto de llamada. Esto significa que ya no puede crear dicho objeto en la pila y, por lo general , no puede llamar.shared_from_this()
desde un constructor o destructor.fuente
shared_ptr
basado en un construido por defectoshared_ptr
y lo que sea que desee señalar ...shared_ptr
son irrelevantes para esta pregunta.shared_from_this
Las condiciones previas establecen claramente que el objeto debe ser propiedad (no solo señalado) por algunosshared_ptr
en el punto de llamada.shared_ptr
Se requiere la propiedad de a en el punto de llamada, pero en un patrón de uso típico, es decir, algo comoshared_ptr<Foo> p(new Foo());
,shared_ptr
asume la propiedad del objeto solo después de que esté completamente construido. Es posible evitar esto creando unshared_ptr
constructor inicializado conthis
y almacenándolo en algún lugar no local (por ejemplo, en un argumento de referencia) para que no muera cuando el constructor se complete. Pero es poco probable que este enrevesado escenario sea necesario.Tiene varios problemas en su diseño, que parecen provenir de una mala comprensión de los punteros inteligentes.
Los punteros inteligentes se utilizan para declarar la propiedad. Está rompiendo esto al declarar que ambos padres son dueños de todos los niños, pero también que cada niño es dueño de su padre. Ambos no pueden ser verdad.
Además, está devolviendo un puntero débil en
getChild()
. Al hacerlo, declaras que la persona que llama no debería preocuparse por la propiedad. Ahora bien, esto puede ser muy limitante, pero también al hacerlo, debe asegurarse de que el niño en cuestión no sea destruido mientras aún se mantienen los punteros débiles, si usara un puntero inteligente, se resolvería por sí solo .Y lo último. Por lo general, cuando acepta nuevas entidades, generalmente debe aceptar punteros sin formato. El puntero inteligente puede tener su propio significado para intercambiar hijos entre padres, pero para uso general, debe aceptar punteros sin formato.
fuente