为什么在c ++ 17中不推荐使用std :: allocator的构造和销毁函数?

时间:2016-09-09 15:05:31

标签: c++ memory-management language-lawyer allocator c++17

c ++ 17规范不赞成construct对象的destroystd::allocator成员。工作组在“弃用std :: allocator的冗余成员”标题下提供了弃用其他成员函数here的理由。

但是,他们没有具体提到为什么这两个成员被弃用或者建议取代该功能的原因。我假设其含义是改为使用std::allocator_traits::construct

我有点困惑的是,在某些情况下实际上是否仍然需要实施construct,因为this comment about std::allocator_traits::construct

  

因为此函数提供自动回退到placement new,所以成员函数construct()是自C ++ 11以来的可选Allocator要求。

对于自定义分配器(例如,对于使用memalign的页面对齐内存),是否会回退到展示位置new始终产生正确的行为?

2 个答案:

答案 0 :(得分:20)

allocator requirements table表示construct(c, args)(如果提供)必须“在C”构建c类型的对象。

它绝对没有说明1)将哪些参数传递给C的构造函数或2)如何传递这些参数。这是分配器的选择,实际上标准中的两个分配器在将它们传递给C的构造函数std::scoped_allocator_adaptorstd::pmr::polymorphic_allocator之前会弄乱参数。特别是在构造std::pair时,它们传递给pair的构造函数的参数可能与它们收到的参数不同。

也没有要求完美前进;如果效率低下,C ++ 03风格construct(T*, const T&)符合要求。

std::allocator的{​​{1}}和construct已被弃用,因为它们没用:没有好的C ++ 11及更高版本的代码应该直接调用它们,并且它们在默认情况下不会添加任何内容

处理内存对齐应该是destroy的任务,而不是allocate

答案 1 :(得分:9)

这些功能与论文D0174R0 Deprecating Vestigial Library Parts in C++17中的其他功能一起被删除。如果我们查看相关部分,我们有

  

std :: allocator的许多成员冗余地重复由std::allocator_traits<allocator<T>>生成的行为,并且可以安全地删除以简化此类。此外,作为自由函数的地址取代std::allocator<T>::address,其需要正确类型的分配器对象。最后,引用类型别名最初是作为与其他分配器进行扩展的预期方式提供的,但在我们指定分配器要求时却证明它没有用处(17.6.3.5 [allocator.requirements])。

     

虽然我们无法在不破坏与显式使用此分配器类型的代码的向后兼容性的情况下删除这些成员,但我们不应该建议继续使用它们。如果某个类型想要支持通用分配器,它应该通过allocator_traits访问分配器的功能,而不是直接访问分配器的成员 - 否则它将不能正确支持依赖于特性的分配器合成默认行为。类似地,如果用户不打算支持泛型分配器,那么直接调用new,delete和直接假设std :: allocator的其他属性(如指针类型)要简单得多。

强调我的

所以理性的是我们不需要复制allocator中的所有代码,因为我们有分配器特性。如果我们查看std::allocator_traits,我们会看到它确实有

allocate
deallocate
construct
destroy
max_size

静态函数,所以我们可以使用那些而不是分配器中的那些。