c++ - 为什么新对象的成员没有被 std::make_unique 初始化?

标签 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;
}

最佳答案

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

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

你的 components[std::type_index(typeid(T))]返回另一个 map 和 .at()返回 std::unique_ptr .您最初是在转换 unique_ptr使用导致未定义行为的 reinterpret_cast。

当我们讨论这个主题时,不要使用 reinterpret_cast 进行跨层次结构的转换。使用 dynamic_cast . dynamic_cast当引用和指针的转换都失败时具有明确定义的行为。

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

关于c++ - 为什么新对象的成员没有被 std::make_unique 初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55290807/

相关文章:

c++ - 使用平台工具集 v100 的 Visual Studio 2012。无法打开源文件 "atlbase.h"

c++ - 在 Lua 中访问 Light 用户数据

c++ - 在单独的文件中运行对象的成员函数

c++ - 每个 undefined symbol 是否都与它来自的库名称相关联?

C++ 如何将连续的区间插入到 std::vector 中?

c++ - boost asio多播重新加入一个组

c++ - 我如何编码类似std::variant的开关?

c++ - 创建类型特征以检测 C++ 中的仿函数

c++ - 在编译时触发 void constexpr?

c++ - 隐式转换产生 "error: taking address of temporary"(GCC vs clang)