Пустой слабый указатель в enable_shared_from_this

После публичного наследования enable_shared_from_this и инициализации объекта класса при вызове другой функции этого класса я все еще вижу пустой слабый указатель enable_shared_from_this_class при отладке в Visual Studio.

Все существующие вопросы связаны либо с частным наследованием от enable_shared_from_this, либо с вызовом weak_from_this в конструкторе. Это не относится ко мне. В настоящее время я использую структуру C++ catch для тестирования этого сценария в отладчике Visual Studio. В функции Initialize я вижу, что weak_ptr этого объекта пуст.

Заголовочный файл:


template <typename T>
class IInfo
public:
IInfo()
    {}
    virtual ~IInfo()
    {}
    virtual bool RegisterForChange(FUNC_PTR<T> Callback, std::weak_ptr<T>) = 0;
};

template <typename T>
class Info : public IInfo<T>, public std::enable_shared_from_this<Info<T>>
{
public:
    Info() {}
    ~Info() {}
    virtual bool RegisterForChange(FUNC_PTR<T> Callback, std::weak_ptr<T> callerContext) override
    {
        //Some code
        _callerContext = callerContext;
    }
private:
    std::weak_ptr<T> _callerContext;
};


class Env : public std::enable_shared_from_this<Env>
{
public:
    Env();
    bool Initialize();
    static void func(/ some arguments / );
private:
    std::shared_ptr<Info<Env>>_spInfo;
    //other variables
}

Файл CPP:

Env::Env() : _spInfo() // + other variables in initializer list
{
    _spInfo = std::make_shared<Info<Env>>();
}

bool Env::Initialize()
{
    _spInfo->RegisterForChange(FUNC_PTR<Env>func, this->weak_from_this());
}

ТЕСТ-СЛУЧАЙ: (используется фреймворк cpp catch)

Env env;
env.Initialize();

РЕДАКТИРОВАТЬ: Согласно комментариям, спрашивая правильно, модуль Env будет управляться плагином, который создаст unique_ptr и вызовет Initialize. Что-то типа:

    template<typename T>
    std::unique_ptr<T> BringUp()
    {
        std::unique_ptr<T> ptr(std::make_unique<T>());
        if (ptr && ptr->Initialize())
            return std::move(ptr);
    }

std::unique_ptr<Env> _envPtr;
_envPtr = BringUp<Env>();

Я все еще сталкиваюсь с той же проблемой. Как мне управлять Env в этом случае?


person Piyush Gupta    schedule 11.05.2019    source источник
comment
Непонятно, что вы ожидаете от этого кода. std::enable_shared_from_this предназначен для объектов, которыми управляет shared_ptr, env не управляется умным указателем   -  person 463035818_is_not_a_number    schedule 12.05.2019
comment
^^^^ Env env; Это уже проблема. Ваш класс не может просто наследовать от std::enable_shared_from_this. На самом деле его нужно создать и управлять им как std::shared_ptr<Env>. пример: auto env = std::make_shared<Env>(); env->Initialize();   -  person WhozCraig    schedule 12.05.2019
comment
я добавил данные к моему вопросу, чтобы задать его правильно.   -  person Piyush Gupta    schedule 12.05.2019


Ответы (1)


Ваш строительный код все еще неверен. Чтобы shared_from_this работал, время жизни объекта должно управляться общими указателями. Сначала вы попытались управлять им по области действия, а затем попытались управлять им с помощью уникального указателя. Ни один из них не будет работать.

Смысл shared_from_this в том, чтобы позволить продлить время жизни объекта с помощью кода, который должен его продлить. Чтобы это работало, время жизни объекта должно управляться некоторой структурой, позволяющей объектам продлевать свою жизнь. Область действия не может этого сделать, потому что когда область действия заканчивается, память объекта освобождается. unique_ptr не может этого сделать, потому что в любой момент времени может существовать только один указатель на объект, поэтому нет способа продлить его жизнь, поскольку для этого потребовались бы два указателя (один должен уже существовать, иначе он будет мертв, а другой — расширять). его жизнь была бы другой).

Создайте объект Env, используя std::make_shared, и сохраните в нем std::shared_ptr.

    template<typename T>
    std::shared_ptr<T> BringUp()
    {
        std::shared_ptr<T> ptr(std::make_shared<T>());
        if (ptr && ptr->Initialize())
            return std::move(ptr);
    }

std::shared_ptr<Env> _envPtr;
_envPtr = BringUp<Env>();
person David Schwartz    schedule 11.05.2019
comment
спасибо за подробное объяснение. Я нашел вопрос link где люди пытались создать хак, но я не уверен, что это правильный путь. - person Piyush Gupta; 12.05.2019
comment
Вы можете взломать его, чтобы у вас был shared_ptr с пустым удалением. Но весь смысл общих указателей заключается в том, чтобы позволить продлить время жизни объекта, и это нанесет ущерб. - person David Schwartz; 12.05.2019