【问题标题】:unordered_set::find and noexceptunordered_set::find 和 noexcept
【发布时间】:2016-03-24 04:23:35
【问题描述】:

我有以下 unordered_set:

class ArtifactImpl{...};

class ArtifactSetKeyOps
{
  public:
    std::size_t operator()(const ArtifactImpl& artifact) const noexcept;
    bool operator()(const ArtifactImpl& lhs, const ArtifactImpl& rhs) const noexcept;
};

std::unordered_set<ArtifactImpl,
  ArtifactSetKeyOps,ArtifactSetKeyOps> artifactSet_;

请注意,我的哈希和谓词模板参数有一个 noexcept 规范。

  • unordered_set::find 可以抛出吗?

我知道 find 没有标记为 noexcept,但实际上 find 不应该执行分配...

  • 是否可以从带有 noexcept 标记的函数调用 find ?

例如:

const ArtifactImpl& foo() noexcept
{
  auto pos = artifactSet_.find(key);
  //etc...
}

尽管上面的 foo() 违反了 find 的 noexcept 规范,但我想知道该规范是否实际上适用于如果提供自己的 noexcept 哈希和比较。

【问题讨论】:

    标签: c++ c++11 unordered-set


    【解决方案1】:

    tl;dr: noexcept 似乎只对移动构造函数/赋值运算符有用。

    如果您敢于接受cplusplus.com 甚至我作为足够的权威:它不会抛出任何异常,除非某个方面发生 - 例如分配器或比较器抛出,什么都不会抛出。
    (我可能现在应该去挖掘相关的 ISO 段落......)

    但是,据我了解,noexcept 在这里并不是特别有用:

    Andrzej has a detailed explanation on his blog,我在这里(错误地)引用了相关部分:

    • noexcept 尽管有规范,但如果实现抛出,则不会买太多
    • 它无助于实施无抛出异常安全保证
    • 除了与移动语义相关的一种情况外,不太可能启用重大优化:

    对于某些函数,例如 vector&lt;T&gt;::push_back 使用 T 的移动构造函数/赋值而不是复制构造函数/赋值可以显着提高性能。但是,如果此移动构造函数/赋值可能会抛出,push_back 将失去强大的异常安全保证。为了利用移动操作(在可能的情况下)并同时保持强保证,需要有一种方法来确定给定的移动操作是否可能抛出,并使用它或替代地回退好旧的抄袭。这正是std::move_if_noexcept 函数所做的,但它需要在适当的地方将 T 的操作标记为 noexcept。

    【讨论】:

    • 您的回答内容丰富。我的印象是动态抛出规范(包括不抛出)完全被 noexcept 取代,从这里:“noexcept 是 throw() 的改进版本,在 C++11 中已弃用。与 throw() 不同,noexcept 将不调用 std::unexpected 并且可能会或可能不会展开堆栈,这可能允许编译器在没有 throw() 的运行时开销的情况下实现 noexcept。”在:en.cppreference.com/w/cpp/language/noexcept_spec
    • 我有一段代码只是执行搜索,而 IMO 应该不可能抛出它,因此我想添加说明符。这也简化了测试(这将涉及注入一个永远不应该发生的异常......)并处理它,以确保更高的代码覆盖率......:-(。在这种情况下,您是否宁愿使用 nothrow 说明符?
    • > 你会在这种情况下吗 - 似乎还没有人真正确切地知道;但钟摆朝“把它放在合适的地方,因为它不会造成伤害(AFAweK)”在这个假设下,我会说,是的,你的foo应该是noexcept,唯一的不同之处在于您得到的是std::terminate,而不是(意外的,因此很可能未处理)异常。
    【解决方案2】:

    如果你散列函数(它必须调用)抛出,它可能会抛出。仅出于这个原因,我不会使用它。但更重要的是,我不会使用 noexcept 说明符,因为它违反了 find 函数的规范。

    【讨论】:

    • 请注意,我提供了一个具有 noexcept 规范的显式哈希函数。我已经知道你所说的一切。
    • @WernerErasmus 对不起,我错过了。但我坚持我的第二个声明。
    • 请编辑答案的第一部分。第二部分没有帮助,但确实如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-03
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 2018-07-20
    相关资源
    最近更新 更多