是的,我看过 C++ 标准 我可以找到(或草稿),但我没有找到 STL 容器提供的任何全面的异常保证。我能找到的只是偶尔有不完整描述的部分 一些 的函数为 一些 的类型。或者也许它就在那里,但我只是没有找到它,我不知道。

笔记: 我是 不是 要求列出人们能想到的所有保障,基本上是 这个问题.
我正在寻找 权威来源 该信息本身的信息 - 或者最好是源的免费版本(例如标准草案),我或多或少可以将其视为官方的。

有帮助吗?

解决方案

阅读标准可能会让人感到害怕(让我们回到标准),但是 Bjarne Stroustrup 在他的《C++ 编程语言》一书中就这个主题编写了一个非常好的附录。他将此附录发布于

http://www.stroustrup.com/3rd_safe0.html , 在http://www.stroustrup.com/3rd_safe.pdf

它相当长且详细(而且写得很好)。例如,您可能会发现 E.4 节很有趣,引用:

E.4 标准集装箱保证

如果图书馆操作本身会引发异常,则可以并且确实可以确保其操作的对象保持在定义明确的状态。例如,at()向矢量抛出out_of_range(第16.3.3节)并不是矢量例外安全性的问题。AT()的作者没有问题,请确保向量在投掷之前处于明确的状态。

此外,E.4.1 节规定

除了基本保证外,标准库还为插入或删除元素的一些操作提供了强大的保证。

看看956页。它包含向量、双端队列、列表和映射的各种操作的保证表。总之,这些容器上的所有操作要么是无抛出的,要么是强的,除了 N - 元素插入到地图中 从而提供了基本的保障。

笔记:上面的文本是旧的并且不涉及 C++11,但对于大多数目的和目的来说仍然应该足够正确。

当谈到 C++11 时...

标准首先规定了关于容器的内容array, deque, forward_list, list, vector, map, set, unordered_map, unordered_set, queue,stack:在

23.2.1/10:

除非另有说明(请参见23.2.4.1,23.2.5.1,23.3.4和23.3.6.5)本条款中定义的所有容器类型符合以下其他要求:

- 如果在插入单个元素时通过插入()或emplace()函数抛出异常,则该函数没有效果。
- 如果通过push_back()或push_front()函数抛出异常,则该函数没有效果。
- no erase(),clear(),pop_back()或pop_front()函数会引发异常。
- 返回迭代器的复制构造函数或分配运算符会引发异常。
— 没有 swap() 函数抛出异常。
- 没有Swap()函数无效任何参​​考的引用,指针或迭代器,引用了要交换的容器的元素。

上面提到的各个部分中指出的怪癖(每个称为异常安全保证)主要是关于特殊的极端情况,例如处理包含类型的散列、比较操作以及抛出交换和抛出移动的异常时运营。

其他提示

n3376

23.2.1一般容器要求[Container.Requirements.general]

第10段

除非另有说明(见23.2.4.1,23.2.5.1,23.3.3.4和23.3.5)本条款中定义的所有容器类型符合以下附加要求:
- 如果插入单个元素的同时抛出Insert()或Emplace()函数,则该函数没有效果。
- 如果由push_back()或push_front()函数抛出异常,则该函数没有效果。
- 没有erase(),clear(),pop_back()或pop_front()函数抛出异常。
- 返回迭代器的副本构造函数或赋值运算符抛出异常。
- 没有Swap()函数抛出异常。
- 没有Swap()函数使任何引用,指针或迭代器无效,引用被交换的容器的元素。
[注意:结束()迭代器不引用任何元素,因此它可能无效。 - endnote]

23.2.4关联容器[关联.Reqmts]

23.2.4.1例外安全保障[Assocative.reqmts.except]

1对于关联容器,没有clear()函数抛出异常。擦除(k)不会抛出异常,除非容器的比较对象(如果有的话)抛出异常。
2对于关联容器,如果在插入或emplace函数内插入单个元素的任何操作抛出异常,则插入无效。

3对于关联容器,没有交换函数抛出异常,除非容器比较对象的交换(如果有的话)抛出该例外。

23.2.5无序关联容器[unord.req]

23.2.5.1异常安全保障[UNORD.REQ.EXCEPT]

1对于无序关联容器,没有Clear()函数抛出异常。擦除(k)不会抛出异常,除非容器的哈希或PRED对象(如果有的话)抛出异常。
2对于无序关联容器,如果通过从插入或emplace函数中插入单个元素的emplate函数以外的任何操作抛出异常,则插入无效。
3对于无序关联容器,除非容器哈希或PRED对象的交换(如果有的话)抛出该例外,否则没有交换函数抛出异常。 4对于无序关联容器,如果从容器的哈希函数或比较函数以外的rehash()函数中抛出异常,则Rehash()函数没有效果。

23.3.3.4排放调节剂[deque.modifiers]

void push_back(t && x);第2段

备注:如果除了通过复制构造函数抛出异常,移动构造函数,赋值运算符或移动的转移分配运算符没有效果。如果由非复制因素t的移动构造函数抛出异常,则效果未指定。

迭代器擦除(Const_iterator First,Const_iterator最后);第6段

抛出:除非由复制构造函数,移动构造函数,分配运算符或移动t的分配运算符抛出异常,否则无例外。

23.3.6.5载体修饰符[vector.modifiers]

void push_back(t && x);第2段

如果由非复制因素t的移动构造函数抛出异常,则效果未指定。

迭代器擦除(Const_iterator First,Const_iterator最后);第5段

抛出:除非由复制构造函数,移动构造函数,分配运算符或移动t的分配运算符抛出异常,否则无例外。

您链接到的文档,N3337标准标准,可作为官员视为官方。这是C ++ 11标准加上未成年人的变化。

你只需要学习阅读标准,这是可以理解的,因为它并非易于阅读。

要查找任何特定库操作的例外保证,请检查操作的备注和评论的规范。如果该函数是成员函数,则检查类型的类型,以了解异常安全性以及它满足的要求。然后检查必须由对象制作以满足这些要求的例外保证的满足要求。

对于通用类型和算法还检查在模板参数上的要求,以便查看这些类型必须满足的要求,以便为包含类型或算法或成员函数所做的所有例外保证(如果是模板参数不符合指定的要求,然后使用与这些参数的模板具有未定义的行为,并且均未适用模板规格)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top