“可平凡重新定位”与“移动后可平凡析构”

主要观点:除了使用 P1144 式或偶尔 P2786 式的简单可重定位库外,还有至少两个使用P1029R2式“移动后简单可销毁”的库;展示了is_trivially_relocatableis_trivially_destructible_after_move的区别;通过std::liststd::deque的例子说明不同实现中这两个特性的不同;提到许多类型在移动构造后可简单销毁,但在移动赋值后不可简单销毁,使用is_trivially_destructible_after_move时要谨慎,且这些特性对于从T类型“移动”到不同U类型的操作不适用。

关键信息:

  • 提到的两个实现is_trivially_destructible_after_move的库:Domagoj Šarić 的psiha/vm定义了trait moved_out_value_is_trivially_destructible;Artur Bać 的arturbac/small_vectors定义了concepts::relocatable
  • std::list的两种实现策略:微软 STL 的“哨兵节点”策略,每个list结尾有额外的分配节点(哨兵);libstdc++和 libc++的“伪节点”策略,list对象自身包含“伪”节点,由 prev/next 指针对组成。
  • std::deque在 libstdc++中is_trivially_relocatable<std::deque<int>>trueis_trivially_destructible_after_move<std::deque<int>>false
  • 许多类型在移动构造后可简单销毁但在移动赋值后不可简单销毁,如 libstdc++的string

重要细节:

  • 标准 C++中 P1144 式库算法uninitialized_relocate的定义。
  • std::list在不同实现下移动构造和销毁的过程及指针变化。
  • 代码示例中展示的各种操作及可能出现的问题,如inplace_vectoroperator=T为 libstdc++的string时会泄漏内存,transfer函数在特定类型时会泄漏内存等。
阅读 9
0 条评论