Shared pointers to a singleton do not recognize each other

前端 未结 2 1741
臣服心动
臣服心动 2021-02-10 08:03

I am currently learning how to use the C++11 smart pointers while programming a 2D game engine as a hobby using SDL. However, I ran into a problem while implementing an OOp wrap

相关标签:
2条回答
  • 2021-02-10 08:34

    Rather than keeping a raw pointer in your static member, you should keep a weak_ptr. Use the lock() function to convert back to a shared_ptr; if it comes back empty then you need to allocate a new singleton object.

        static shared_ptr<Foo> getInstance()
        {
            shared_ptr<Foo> p = instance_.lock();
            if (!p)
            {
                p = new Foo;
                instance_ = p;
            }
            return p;
        }
    private:
        static weak_ptr<Foo> instance_;
    
    0 讨论(0)
  • 2021-02-10 08:44

    Your method could look like this:

    static shared_ptr<Foo> getInstance()
    {
        static std::shared_ptr<Foo> instance = std::make_shared<Foo>();
        return instance;
    }
    

    That way only a single, static instance is created (since C++11 this is also thread-safe) and you are always returning a copy from the static shared_ptr, which means all shared pointers that are returned share ownership.

    Your original attempt created separate instances of shared_ptr from the same plain pointer, but this leads to detached ownership since the different shared pointers have no knowledge of each other and each one has its own internal "shared count".


    Update: Re-reading your question I think you don't want to extend the life-time until the end of the program. Consider this method to destroy the instance as soon as all the returned shared pointers went out of scope:

    static std::shared_ptr<Foo> getInstance()
    {
        static std::weak_ptr<Foo> instance;
        static std::mutex mutex; // (a)
        const std::lock_guard< std::mutex > lock( mutex ); // (b)
        if( const auto result = instance.lock() ) return result;
        return ( instance = std::make_shared<Foo>() ).lock();
    }
    

    where you could delete the lines marked (a) and (b) if you are not in a multi-threaded environment.

    Note that this is actually a so-called phoenix-singleton, meaning that if all shared pointers you received from getInstance() went out of scope and the instance was deleted, the next call to getInstance() will create another new instance of Foo.

    0 讨论(0)
提交回复
热议问题