【问题标题】:Why there is no std::uninitialized_move_if_noexcept?为什么没有 std::uninitialized_move_if_noexcept?
【发布时间】:2018-10-23 07:20:47
【问题描述】:

C++17 添加了std::uninitialized_move,但没有std::uninitialized_move_if_noexcept 会在内部使用std::move_if_noexcept。在我看来,它会很有用,因为现在,如果我们想重新分配,我们仍然需要写一些东西

if constexpr (!std::is_nothrow_move_constructible_v<value_type>
              && std::is_copy_constructible_v<value_type>)
  std::uninitialized_copy(...);
else 
  std::uninitialized_move(...); 

C++17 中没有引入std::uninitialized_move_if_noexcept 有什么特别的原因吗?

【问题讨论】:

    标签: c++ c++17 move placement-new noexcept


    【解决方案1】:

    一篇关于"Extending memory management tools"open-std.org 的论文有一个关于uninitialized_move 的部分处理这个问题。

    有人对uninitialized_move 的异常处理提出了一些担忧。如果移动构造函数抛出,则源对象可能已受到不可挽回的损坏。由于这个问题没有解决方案,我们实现了自然和预期的语义,即销毁目标缓冲区中所有完全构造的对象并传播异常。这与uninitialized_copy 的行为尽可能接近。 另一种算法uninitialized_move_if_noexcept 可被视为解决此问题的方法。在 libstdc++ 中已经使用move_if_noexcept 迭代器实现了这样的算法。 鉴于目前没有基于范围的move_if_noexcept 算法,此处不考虑这种解决方案。然而,这样的功能似乎很容易实现。

    【讨论】:

    • 什么是move_if_noexcept迭代器?标准库中只有std::move_iterator,但没有std::move_if_noexcept_iterator
    • 我认为论文指的是这个:en.cppreference.com/w/cpp/utility/move_if_noexcept
    • 实际上,uninitialized_move 可以简单地将所有完全构造的对象从目标缓冲区复制分配回源缓冲区,前提是该类型不可复制分配。然后像它一样销毁目标缓冲区中所有完全构造的对象。这种方法也很容易实现。这仍然是一个弱/基本的异常保证,但仍然比将所有完全移动的对象保持在未指定但有效的状态更好。这样所有可以复活的对象都复活了。
    猜你喜欢
    • 2017-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多