2010-12-13 5 views
10

Я просто играю с умными указателями в новом новом стандарте C++. Однако я не понимаю использования функции shared_from_this. Вот что у меня есть:enable_shared_from_this (C++ 0x): что я делаю неправильно?

#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(); 
} 

и бросает зЬй :: bad_weak_ptr исключение в строке

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

если я вместо того, чтобы сделать

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

это работает, и я могу после этого сделать

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

так должен быть объект принадлежат одному shared_ptr, прежде чем я смогу использовать shared_from_this? Но как я могу знать это заранее?

ответ

22

Это предварительное условие использования shared_from_this, что должно существовать хотя бы один shared_ptr, которому принадлежит данный объект. Это означает, что вы можете использовать только shared_from_this для извлечения shared_ptr, которому принадлежит объект, к которому у вас есть ссылка или указатель, вы не можете использовать его, чтобы узнать, принадлежит ли такой объект shared_ptr.

Вам необходимо переделать свой дизайн, чтобы либо вы гарантировали, что любой такой объект находится под управлением shared_ptr, либо что вам никогда не нужно знать, или, наконец, (и наименее желательно) вы создаете другой способ управления это знание.

+0

Не могли бы вы просто поставить блок try вокруг вызова shared_from_this, если бы вы хотели узнать, хранится ли объект shared_ptr? Я не знаю, как он указан в (предстоящем) стандарте, но он не выглядит неопределенным поведением - он бросает исключение. – nobar

+1

@nobar: Это было бы небезопасно. Вы будете полагаться на недокументированные детали реализации. 'shared_from_this' не является методом проверки того, принадлежит ли объект общедоступному указателю; это метод для получения общего указателя от объекта, который вы _know_ принадлежит общедоступному указателю. –

+0

Я думаю, что вы правы. В проекте C++ 0x говорится: «Должен быть хотя бы один экземпляр shared_ptr p, которому принадлежит & t.», Но он не говорит, что происходит иначе. Он показывает реализацию с точки зрения weak_ptr (что подразумевало бы, что исключение будет выведено на ошибку), но это всего лишь «предложение». Интересно, будет ли в конечном итоге исправление ошибок. – nobar

15

Чтобы продлить действие Чарльза, когда вы используете enable_shared_from_this, вы обычно хотите что-то вроде ниже, чтобы гарантировать, что существует 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()' должен быть 'static', не так ли? –

+0

@ abyss.7: Действительно. – ronag

+1

И для совместного использования по умолчанию вы можете использовать что-то в строках: 'try {return shared_from_this(); } catch (const bad_weak_ptr &) {return make_shared (); } ' –

Смежные вопросы