2010-12-13 14 views
10

Estoy jugando con los punteros inteligentes en el próximo nuevo estándar de C++. Sin embargo, no entiendo el uso de la función shared_from_this. Aquí es lo que tengo:enable_shared_from_this (C++ 0x): ¿qué estoy haciendo mal?

#include <iostream> 
#include <memory> 

class CVerboseBornAndDie2 : public std::enable_shared_from_this<CVerboseBornAndDie2> 
{ 
public: 
    std::string m_Name; 
    CVerboseBornAndDie2(std::string name) : m_Name(name) 
    { 
     std::cout << m_Name << " (" << this << ") is born!" << std::endl; 
    } 
    virtual ~CVerboseBornAndDie2() 
    { 
     std::cout << m_Name << " (" << this << ") is dying!" << std::endl; 
    } 
}; 

int main(){ 
    CVerboseBornAndDie2* vbad = new CVerboseBornAndDie2("foo"); 
    std::shared_ptr<CVerboseBornAndDie2> p = vbad->shared_from_this(); 
} 

y lanza un std :: bad_weak_ptr excepción en la línea

std::shared_ptr<CVerboseBornAndDie2> p = vbad->shared_from_this(); 

si en lugar de hacer

std::shared_ptr<CVerboseBornAndDie2> p(vbad); 

funciona y lo que puedo hacer después

std::shared_ptr<CVerboseBornAndDie2> p2 = p.get()->shared_from_this(); 

así que debe el objeto pertenecer a un shared_ptr antes de que pueda usar shared_from_this? ¿Pero cómo puedo saber esto de antemano?

Respuesta

22

Es una condición previa para usar shared_from_this que debe existir al menos un shared_ptr que posee el objeto en cuestión. Esto significa que solo puede usar shared_from_this para recuperar un shared_ptr que posee un objeto del que tiene una referencia o un puntero, no puede usarlo para averiguar si dicho objeto es propiedad de un shared_ptr.

Necesita volver a diseñar su diseño para que tenga garantizado que dicho objeto está siendo administrado por shared_ptr o que no necesita saber o finalmente (y menos deseablemente) crea alguna otra forma de administración este conocimiento.

+0

¿No podría simplemente poner un try-block alrededor de una llamada a shared_from_this si desea saber si el objeto está en manos de un shared_ptr? No sé cómo se especifica en el (próximo) estándar, pero no parece ser un comportamiento indefinido, está lanzando una excepción. – nobar

+1

@nobar: Esto sería inseguro inseguro. Confiaría en los detalles de la implementación no documentada. 'shared_from_this' no es un método para probar si un objeto es propiedad de un puntero compartido; es un método para recuperar un puntero compartido de un objeto que usted sabe que es propiedad de un puntero compartido. –

+0

Creo que tienes razón. El borrador de C++ 0x dice "Habrá al menos una instancia de p compartida que posee & t.", Pero no dice lo que sucede de otro modo. Muestra una implementación en términos de weak_ptr (lo que implicaría que se lanzará una excepción por error), pero eso es solo una "sugerencia". Me pregunto si el manejo de errores eventualmente se especificará mejor. – nobar

15

Para extender la respuesta de Charles, cuando usa enable_shared_from_this, generalmente quiere algo como lo siguiente para garantizar que existe un shared_ptr.

class my_class : public std::enable_shared_from_this<my_class> 
{ 
public: 
    static std::shared_ptr<my_class> create() // can only be created as shared_ptr 
    { 
     return std::shared_ptr<my_class>(new my_class()); 
    } 
private 
    my_class(){} // don't allow non shared_ptr instances. 
}; 
+1

'create()' debe ser 'static', ¿no? –

+0

@ abyss.7: De hecho. – ronag

+1

Y para compartir de manera predeterminada, podría usar algo como: 'try {return shared_from_this(); } catch (const bad_weak_ptr &) {return make_shared (); } ' –

Cuestiones relacionadas