Почему члены нового объекта не инициализируются с помощью std :: make_unique? - PullRequest
0 голосов
/ 22 марта 2019

Несмотря на значения по умолчанию X, Y и Z в Position, когда он инициализируется в create (), кажется, что ни одна из этих переменных не была инициализирована вообще. Я могу установить их, а затем получить их, но значение по умолчанию никогда не видно. Я пытался инициализировать их различными способами, но безуспешно.

Как использовать std :: make_unique для возврата unique_ptr типа T с установленными значениями по умолчанию?

#include <iostream>
#include <unordered_map>
#include <memory>
#include <typeindex>

class Component
{

public:
    Component() {};
    virtual ~Component() {};
};

class Position : public Component
{
public:
    Position(){};
    float x = 123;
    float y = 321;
    float z = 666;
};

std::unordered_map<std::type_index, std::unordered_map<uint32_t, std::unique_ptr<Component>>> components;

template<typename T>
T& get(uint32_t id)
{
    return reinterpret_cast<T&>(components[std::type_index(typeid(T))].at(id));
}

template<typename T>
void create(uint32_t id)
{
    components[std::type_index(typeid(T))].emplace(id, std::make_unique<T>());
}

int main()
{

    create<Position>(8);
    std::cout << get<Position>(8).z << std::endl; //Value not initialized
    get<Position>(8).z;
    std::cout << get<Position>(8).z << std::endl; //Still not
    get<Position>(8) = Position();
    std::cout << get<Position>(8).z << std::endl; //Now works, but unwanted creation of temporary Position
    get<Position>(8).z = 42;
    std::cout << get<Position>(8).z << std::endl; //Works
    //New try
    create<Position>(8);
    return 0;
}

1 Ответ

4 голосов
/ 22 марта 2019

Проблема в вашем методе get.Измените его, как показано ниже, и это должно решить проблему.

return reinterpret_cast<T&>(*(components[std::type_index(typeid(T))].at(id)));

Ваш components[std::type_index(typeid(T))] возвращает другую карту, а .at() возвращает std::unique_ptr.Изначально вы разыгрывали unique_ptr с использованием reinterpret_cast, что привело к неопределенному поведению.

Пока мы обсуждаем эту тему, не используйте reinterpret_cast для приведения к разным иерархиям.Используйте dynamic_cast.dynamic_cast имеет четко определенное поведение при сбое приведения как для ссылок, так и для указателей.

Короче говоря, вы выполняли reinterpret_cast<Position&>(uniquePtrToPosition), что является недопустимым C ++.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...