Утверждение для принудительного создания объекта как shared_ptr? - PullRequest
0 голосов
/ 06 мая 2020

При использовании std::shared_ptr часто бывает полезно использовать std::enable_shared_from_this<T>, чтобы у вас был доступ к функции shared_from_this().

Одно из требований использования shared_from_this() состоит в том, что все экземпляры объекта создаются с использованием std::shared_ptr. Хотя это совершенно нормальное требование, очень сложно применить к для будущих пользователей этого класса.

Если я создаю объект:

class MyClass : public std::enable_shared_from_this<MyClass>
{
public:
    MyClass()
    {

    }

    void doAThing()
    {
        // something I need done asynchronously
    }

    void someFunction()
    {
        std::weak_ptr<MyClass> w (shared_from_this());

        // we need to use a lambda that is executed asynchronously and
        // so we pass the std::weak_ptr to it to check this object still exists it is executed
        std::function<void()> f = [w]()
        {
            if (! w.expired())
                w.lock()->doAThing();
        };


        callAsynchronously (f); // this function passes the lambda to some queue and executes it asynchronously
    }
};

, а затем кто-то - возможно, спустя годы - использует этот класс, не создавая его как shared_ptr ...

MyClass m;
m.someFunction();

тогда мы получаем ошибку времени выполнения sh:

libc++abi.dylib: terminating with uncaught exception of type std::__1::bad_weak_ptr: bad_weak_ptr

Для ясности, я понимаю, что решение этой проблемы:

std::shared_ptr<MyClass> m = std::make_shared<MyClass>();
m->someFunction();

(конечно, необходимо убедиться, что shared_ptr существует достаточно долго для выполнения асинхронного обратного вызова, но я игнорирую это здесь. объект, который наследуется от std::enable_shared_from_this<T>, так что любая конструкция этого объекта не как std::shared_ptr выбирается во время компиляции , а не во время выполнения?

1 Ответ

1 голос
/ 06 мая 2020

Следующий код с функцией create работал у меня без исключения.

#include <memory>

class X : public std::enable_shared_from_this<X> {
    private:
        X() = default;

    public:
        static std::shared_ptr<X> makeX() {
            return std::shared_ptr<X>(new X());
        }

        void doSth() {
            auto sharedPtr = shared_from_this();
            // do sth
        }
};

int main() {
    auto x = X::makeX();
    x->doSth();
}
...