为什么新对象的成员没有用std :: make_unique初始化?

时间:2019-03-21 23:40:29

标签: c++ c++17

尽管Position中X,Y和Z的默认值是在create()中初始化的,但似乎这些变量似乎都没有初始化。我可以设置它们然后检索它们,但是从未看到默认值。我尝试过用各种方法初始化它们,但是没有成功。

如何使用std :: make_unique返回具有默认值的T类型的unique_ptr?

#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 个答案:

答案 0 :(得分:4)

问题出在您的get方法中。如下更改它,它应该可以解决问题。

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

您的components[std::type_index(typeid(T))]返回另一个映射,而.at()返回一个std::unique_ptr。您最初是使用reinterpret_cast投射unique_ptr的,这导致未定义的行为。

尽管我们处于主题上,但不要使用reinterpret_cast进行层次结构转换。使用dynamic_cast。当对引用和指针的转换均失败时,dynamic_cast具有明确定义的行为。

简而言之,您正在做reinterpret_cast<Position&>(uniquePtrToPosition),这是非法的C ++。