在哪里可以找到标准容器和算法的所有异常保证?

Meh*_*dad 22 c++ exception c++-faq standard-library exception-safety

是的,我已经查看了我能找到的C++标准(或草稿),但我没有找到STL容器给出的任何全面的异常保证.我所能找到的只是偶尔的部分,对某些类型的某些函数的描述不完整.或许它就在那里,但我只是找不到它,我不知道.

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

Joh*_*erg 15

阅读标准可能会让人感到害怕(让我们回到标准),但是Bjarne Stroustrup在他的"The C++ Programming Language"一书中写了一篇关于这个主题的非常好的附录.他把这个附录贴在了

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 - 元素插入到map中提供基本保证.

注意:上面的文字是旧的,不涉及C++ 11,但对于大多数目的和目的应该仍然是正确的.

谈到C++ 11 ......

标准首先陈述,关于容器 array, deque, forward_list, list, vector, map, set, unordered_map, unordered_set, queue,stack:at

23.2.1/10:

除非另有规定(见23.2.4.1,23.2.5.1,23.3.3.4和23.3.6.5),本条款中定义的所有容器类型均满足以下附加要求:

- 如果插入单个元素时insert()或emplace()函数抛出异常,则该函数不起作用.
- 如果push_back()或push_front()函数抛出异常,则该函数不起作用.
- 没有erase(),clear(),pop_back()或pop_front()函数抛出异常.
- 没有复制构造函数或返回迭代器的赋值运算符会引发异常.
- 没有swap()函数抛出异常.
- 没有swap()函数使任何引用,指针或迭代器无效,引用被交换的容器的元素.

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


Mar*_*ork 8

n3376

23.2.1一般容器要求[container.requirements.general]

第10段

除非另有规定(参见23.2.4.1,23.2.5.1,23.3.3.4和23.3.6.5),本条款中定义的所有容器类型均满足以下附加要求:
- 如果插入()或emplace()抛出异常插入单个元素时,该函数没有任何影响.
- 如果push_back()或push_front()函数抛出异常,则该函数不起作用.
- 没有erase(),clear(),pop_back()或pop_front()函数抛出异常.
- 没有复制构造函数或返回迭代器的赋值运算符会引发异常.
- 没有swap()函数抛出异常.
- 没有swap()函数使任何引用,指针或迭代器无效,引用被交换的容器的元素.
[注意:end()迭代器不引用任何元素,因此它可能无效.-endnote]

23.2.4关联容器[associative.reqmts]

23.2.4.1异常安全保证[associative.reqmts.except]

1对于关联容器,没有clear()函数抛出异常.erase(k)不会抛出异常,除非容器的Compare对象(如果有)抛出该异常.
2对于关联容器,如果插入或插入单个元素的emplace函数中的任何操作抛出异常,则插入无效.
3对于关联容器,除非交换容器的Compare对象(如果有)抛出异常,否则交换函数不会抛出异常.

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

23.2.5.1异常安全保证[unord.req.except]

1对于无序关联容器,没有clear()函数抛出异常.erase(k)不会抛出异常,除非容器的Hash或Pred对象(如果有)抛出该异常.
2对于无序关联容器,如果插入单个元素的插入或插入函数中的容器的散列函数以外的任何操作抛出异常,则插入无效.
3对于无序关联容器,除非交换容器的Hash或Pred对象(如果有)抛出异常,否则交换函数不会抛出异常.
4对于无序关联容器,如果从rehash()函数中抛出异常而不是容器的散列函数或比较函数,则rehash()函数无效.

23.3.3.4 deque modifiers [deque.modifiers]

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

备注:如果除了复制构造函数之外抛出异常,则移动构造函数,赋值运算符或T的移动赋值运算符没有任何影响.如果非CopyInsertable T的移动构造函数抛出异常,则不指定效果.

iterator erase(const_iterator first,const_iterator last); 第6段

抛出:除非复制构造函数,移动构造函数,赋值运算符或T的移动赋值运算符抛出异常,否则无效.

23.3.6.5向量修饰符[vector.modifiers]

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

如果非CopyInsertable T的移动构造函数抛出异常,则不指定效果.

iterator erase(const_iterator first,const_iterator last); 第5段

抛出:除非复制构造函数,移动构造函数,赋值运算符或T的移动赋值运算符抛出异常,否则无效.