提问人:user541686 提问时间:7/28/2012 最后编辑:Communityuser541686 更新时间:3/13/2015 访问量:4758
在哪里可以找到标准容器和算法的所有例外保证?
Where can I find all the exception guarantees for the Standard Containers and Algorithms?
问:
是的,我已经查看了我能找到的 C++ 标准(或草案),但我没有找到任何全面的 STL 容器提供的例外保证。我能找到的只是偶尔的部分,其中对某些类型的某些函数的描述不完整。或者也许它在那里,但我只是没有找到它,我不知道。
注意:我不是在要求列出人们能想到的所有保证,这基本上就是这个问题。
我正在寻找这些信息本身的权威来源——或者最好是来源的免费版本(例如标准草案),我或多或少可以将其视为官方信息。
答:
阅读标准可能很可怕(让我们回到标准),但是Bjarne Stroustrup在他的书“C++编程语言”中写了一个非常好的附录。他将这个附录发布在
http://www.stroustrup.com/3rd_safe0.html , at http://www.stroustrup.com/3rd_safe.pdf
它很长很详细(而且写得很好)。例如,您可能会发现 E.4 部分很有趣,引用:
E.4 标准集装箱保证
如果库操作本身引发异常,它可以 - 并且确实 - 确保它所操作的对象保留在 明确定义的状态。例如,at() 抛出 out_of_range 向量 (§16.3.3) 不是向量异常安全的问题 .at() 的编写者可以毫无问题地确保向量位于 投掷前定义明确的状态。
此外,E.4.1节指出
除了基本保证之外,标准库还提供 对插入或删除元素的少数操作有很强的保证。
请看第 956 页。它包含矢量、deque、list 和 map 的各种操作的保证表。总之,这些容器上的所有操作要么是 nothrow 要么是 strong,除了 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.3.4和 23.3.6.5) 本条款中定义的所有集装箱类型均符合下列附加要求:
— 如果 insert() 或 emplace() 函数抛出异常,而 插入单个元素,该函数不起作用。
— 如果 push_back() 或 push_front() 函数抛出异常, 该功能没有任何效果。
— 没有 erase()、clear()、pop_back() 或 pop_front() 函数抛出 例外。
— 没有返回的迭代器的复制构造函数或赋值运算符 引发异常。
— 没有 swap() 函数抛出异常。
— 没有 swap() 函数使任何引用、指针或 迭代器是指正在交换的容器的元素。
上面提到的各个部分(每个部分都称为异常安全保证)中指出的怪癖主要是关于特殊的反墙情况,例如在处理包含类型的哈希、比较操作以及抛出交换和抛出移动操作的异常时。
评论
std::rotate
std::copy
货号 N3376
23.2.1 一般容器要求 [container.requirements.general]
第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() 函数会使引用正在交换的容器元素的任何引用、指针或迭代器无效。
[注意:end() 迭代器不引用任何元素,因此它可能会失效。
23.2.4 关联容器 [associative.reqmts]
23.2.4.1 异常安全保证 [associative.reqmts.except]
1 对于关联容器,没有 clear() 函数会引发异常。erase(k) 不会引发异常,除非该异常是由容器的 Compare 对象(如果有)引发的。
2 对于关联容器,如果插入或放置函数中插入单个元素的任何操作引发异常,则插入不起作用。
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 修饰符 [deque.modifiers]
无效push_back(T&&x);第2段
备注:如果 T 的复制构造函数、移动构造函数、赋值运算符或移动赋值运算符以外的其他原因引发异常,则不会产生任何影响。如果非 CopyInsertable T 的移动构造函数引发异常,则未指定效果。
迭代器擦除(const_iterator first, const_iterator last);第6段
抛出:除非 T 的复制构造函数、移动构造函数、赋值运算符或移动赋值运算符引发异常,否则无任何内容。
23.3.6.5 矢量修饰符 [vector.modifiers]
无效push_back(T&&x);第2段
如果非 CopyInsertable T 的移动构造函数引发异常,则未指定效果。
迭代器擦除(const_iterator first, const_iterator last);第5段
抛出:除非 T 的复制构造函数、移动构造函数、赋值运算符或移动赋值运算符引发异常,否则无任何内容。
评论
vector::insert()
while inserting a **single element**
if an exception is thrown by an insert() or emplace() function while inserting a single element, that function has no effects.
while inserting a **single element**
您链接到的文档(n3337 标准草案)可以被视为官方文档。这是 C++ 标准加上一些小的编辑更改。
你只需要学会阅读标准,这是可以理解的,因为它不是为了容易阅读。
若要查找任何特定库操作的异常保证,请检查该操作的规范,以获取有关异常的注释和注释。如果函数是成员函数,则检查该类型的规范,以获取有关异常安全性及其满足的要求的注释。然后,检查对象为满足这些要求而必须做出的异常保证的满足要求。
对于泛型类型和算法,还要检查对模板参数的要求,以查看这些类型必须满足哪些要求,以便类型或算法或成员函数所做的所有异常保证都保持不变(如果模板参数不满足指定的要求,则使用具有这些参数的模板具有未定义的行为,并且模板的规范均不适用)。
评论
vector::reserve()
resize
at
上一个:C++ 中的对象销毁
下一个:将共享指针作为参数传递
评论
vector::swap
vector::insert
std::swap
associative.reqmts.except
unord.req.except
.modifiers