enable_shared_from_this (c ++ 0x): что я делаю не так? - PullRequest
9 голосов
/ 13 декабря 2010

Я просто играю с умными указателями в новом стандарте c ++. Однако я не могу понять использование функции shared_from_this. Вот что у меня есть:

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

и выдает исключение std :: 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? Но как я могу знать это заранее?

Ответы [ 2 ]

22 голосов
/ 13 декабря 2010

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

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

15 голосов
/ 13 декабря 2010

Чтобы расширить ответ Чарльза, когда вы используете 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.
};
...