std :: set :: find exception guarantee

时间:2013-12-22 23:37:39

标签: c++ exception stl set

我正在编写异常安全的代码,我的设计不需要抛出保证 set :: find方法。 我假设比较器对象总是成功。 这是否意味着set :: find方法总能成功?

在我看到根据http://en.cppreference.com/w/cpp/container/set/erase之后,我想到了这种可能性,set :: erase方法,使用相同的假设,应该总是成功,也许有一个找到它(那么它将是定义的值得文档中的评论!)

问题的直接来源是我需要检查一个元素是否在一个集合中并从集合中删除它 - 所有没有抛出保证(它在catch块中)。

2 个答案:

答案 0 :(得分:1)

std::set::find

  

返回值

     

使用键key的元素的迭代器。如果找不到这样的元素,则返回past-the-end(参见end())迭代器。

文档和C ++标准都没有明确列出任何异常安全保证。但是,std::set::erase中规定的相同规则适用于此处(§23.2.4.1异常安全保证[associative.reqmts.except]):

  除非容器的erase(k)对象(如果有)抛出该异常,否则

Compare不会抛出异常。

实质上,除非Compare对象抛出异常,否则std::set::find不抛出。 Bjarne Stroustrup在The C++ Programming Language, Special Edition - Appendix E中有以下内容:

  

幸运的是,谓词很少做任何可能引发异常的事情。但是,在考虑异常安全时,必须考虑用户定义的<==!=谓词。

如果您未提供任何用户定义的谓词,则可以认为std::set::find不会引发异常。如果是,则应将其标记为noexcept,以便在您的方案中安全地工作。

答案 1 :(得分:0)

C ++ 11 §23.2.4.1异常安全保证[associative.reqmts.except] 列出了关联容器(包括set)的所有异常安全要求,并且没有提及由find组成。所以不,标准不能保证find永远不会抛出。

在没有未定义的行为并且假设一个非投掷比较器的情况下,我发现C ++标准库的实现极不可能从set::find引发异常。我个人会对(a)将set::find包装在noexcept转发函数中感到满意,这样如果发生这种“不可能”的事情,程序就会崩溃,或者(b)包装特定的{{1}调用

set::find

并简单地将异常视为“未找到”。

请注意,关联容器的排序关系是一个容易被忽视的未定义行为的来源:§23.2.4/ 2要求排序关系在关键元素上引入严格的弱排序(如第25.4节所述)。使用严格弱排序的排序关系实例化的关联容器没有定义的行为,其中一个可能的结果是从auto it = foo.end(); try { it = foo.find(bar); } catch(...) {} 抛出异常。