ksl
ksl

Reputation: 4709

std::bad_weak_ptr exception when using shared_from_this

The following code causes a std::bad_weak_ptr exception when the ctor for MyCommand executes but not the function MyCommand::execute.

class Observer
{
public:
    Observer(){}
    virtual ~Observer(){}

    virtual void update(const std::string& msg) = 0;
};

class Command
{
public:
    Command(){}
    virtual ~Command(){}

    virtual void execute() = 0;
};

class MyCommand : public Command, public Observer, public std::enable_shared_from_this<MyCommand>
{
public:
    MyCommand()
    {
        // std::bad_weak_ptr exception
        std::shared_ptr<Observer> observer = shared_from_this();
    }

    virtual ~MyCommand(){}

private:
    virtual void execute()
    {
        // no exception
        std::shared_ptr<Observer> observer = shared_from_this();
    }
    virtual void update(const std::string& msg){}
};

int main(int argc, const char* argv[])
{
    // causes std::bad_weak_ptr exception
    std::shared_ptr<Command> myCommand = std::make_shared<MyCommand>();

    // doesn't cause std::bad_weak_ptr exception
    myCommand->execute();
}

Reading up on enable_shared_from_this, I know that:

Prior to calling shared_from_this on an object t, there must be a std::shared_ptr that owns t.

I need to understand why the exception is thrown in the ctor but not in the execute function.

Is is something to do with the fact that the ctor has not fully executed before shared_from_this is called and therefore the object is not fully constructed?

If not, what is it?

Upvotes: 8

Views: 5456

Answers (2)

Tomer
Tomer

Reputation: 1646

Note: for me the issue was that I did not add the "public" keyword (hopefully this will save others some time).

E.g.:

class A : std::enable_shared_from_this<A> { //BAD
class A : public std::enable_shared_from_this<A> { //GOOD

Upvotes: 11

vasek
vasek

Reputation: 2839

You can't use shared_from_this in constructor since no shared_ptr is assigned yet. See this Why shared_from_this can't be used in constructor from technical standpoint?

However when the object is constructed and there is any shared_ptr associated with the instance, you are able to call shared_from_this as usual.

Upvotes: 15

Related Questions