2

STL 文档说 (1)uninitialized_default_construct调用::new (static_cast<void*>(std::addressof(*p))) Value;.

与 (2) 的唯一区别uninitialized_value_construct是后来调用::new (static_cast<void*>(std::addressof(*p))) Value();. (注意()

我想知道内置类型和非平凡类型的实际区别是什么。

对于内置插件,在我看来,第二个 (2) 将进行值初始化,即将值设置为零,而第一个 (1) 将是空操作(使值未初始化。)

对于非平凡类型 (2) 将调用默认构造函数。我不清楚的是(1)对非平凡类型会做什么。还会调用默认构造函数吗?只要T::T() = default类被设计成这样,它是否也是无操作的,并且它是无操作的并且使元素处于部分形成的状态?

让我感到困惑的是为什么 STL 容器将始终使用uninitialized_value_construct,尽管uninitialized_default_construct在可能的情况下调用会更加一致。

例如std::vector<double>(100)-> 应该uninitialized_default_construct在当前行为可以被模仿时调用std::vector<double>(100, {})or std::vector<double>(100, double{})

这是因为在uninitialized_default_constructSTL 的初始版本中不存在的概念吗?或者根本没有简单的方法将信息传递给容器的构造函数?

4

1 回答 1

2

让我感到困惑的是为什么 STL 容器将始终使用uninitialized_value_construct,尽管uninitialized_default_construct在可能的情况下调用会更加一致。

容器都不使用。容器通过它们的分配器构造对象。不幸的是,allocator_traits<...>::construct它采用任意系列的参数。在默认初始化和值初始化之间不传递参数是不明确的。使用哪一个取决于分配器,但无法通过参数列表选择哪一个。默认allocator_traits::construct将使用值初始化,并且始终对所有类型都这样做。

当前的行为可以被模仿std::vector<double>(100, {})

即使忽略向后兼容性问题以及我刚才所说的关于分配器的内容,该构造函数的意思是“默认构造 adouble然后将其double值一次复制到 100 个元素中”。所以它不会是“当前的行为”。

于 2019-10-04T05:28:34.830 回答