Yes, I've looked at the C++ standards that I could find (or the drafts), but I'm not finding any comprehensive of the exception guarantees given by STL containers. All I can find are occasional sections with incomplete descriptions on some of the functions for some of the types. Or perhaps it's there but I'm just not finding it, I don't know.
是的,我已经查看了我能找到的C ++标准(或草稿),但我没有找到STL容器给出的任何全面的异常保证。我所能找到的只是偶尔的部分,对某些类型的某些函数的描述不完整。或许它就在那里,但我只是找不到它,我不知道。
Note: I'm not asking for a list of all the guarantees people can think of, which is basically in this question.
I'm looking for the authoritative source of this information itself -- or preferably, a free version of the source (e.g. a draft of the standard) where I can more or less treat as official.
注意:我不是要求列出人们可以想到的所有保证,这基本上就是在这个问题中。我正在寻找这些信息本身的权威来源 - 或者最好是源的免费版本(例如标准草案),我可以或多或少地将其视为官方信息。
3 个解决方案
#1
14
Reading the standard can be scary (let's come back to the standard), but Bjarne Stroustrup has written a really nice appendix on this subject in his book 'The C++ Programming Language'. He posted this appendix at
阅读标准可能很可怕(让我们回到标准),但Bjarne Stroustrup在他的“The C ++ Programming Language”一书中写了一篇关于这个主题的非常好的附录。他把这个附录贴在了
http://www.stroustrup.com/3rd_safe0.html , at http://www.stroustrup.com/3rd_safe.pdf
http://www.stroustrup.com/3rd_safe0.html,网址:http://www.stroustrup.com/3rd_safe.pdf
It's pretty long and detailed (and well written). You may for example find section E.4 interesting, quote:
它非常详细(并且写得很好)。例如,您可以找到有趣的E.4节,引用:
E.4 Standard Container Guarantees
E.4标准集装箱保证
If a library operation itself throws an exception, it can – and does – make sure that the objects on which it operates are left in a well-defined state. For example, at() throwing out_of_range for a vector (§16.3.3) is not a problem with exception safety for the vector . The writer of at() has no problem making sure that a vector is in a well-defined state before throwing.
如果库操作本身抛出异常,它可以 - 并且确实 - 确保它所操作的对象处于明确定义的状态。例如,at()为向量抛出out_of_range(第16.3.3节)对于向量的异常安全性不是问题。 at()的作者在投掷之前确保向量处于明确定义的状态是没有问题的。
In addition, section E.4.1 states
此外,E.4.1节说明
In addition to the basic guarantee, the standard library offers the strong guarantee for a few operations that insert or remove elements.
除了基本保证之外,标准库还为插入或删除元素的一些操作提供了强有力的保证。
have a look at page 956. It contains a table of guarantees for various operations for vector, deque, list and map. In summary, all operations on those containers are either nothrow or strong, except for N - element insert into map which offers the basic guarantees.
看看第956页。它包含一个表格,用于表示矢量,双端队列,列表和地图的各种操作。总之,这些容器上的所有操作都是非常的或强大的,除了N - 元素插入到map中提供基本保证。
Note: the above text is old and does not address C++11, but should still be correct enough for most aims and purposes.
注意:上面的文字很旧,并没有解决C ++ 11,但对于大多数目的和目的来说仍然应该是正确的。
When it comes to C++11...
the standard first states, about the containers array, deque, forward_list, list, vector, map, set, unordered_map, unordered_set, queue,stack
: at
标准的第一个状态,关于容器数组,deque,forward_list,list,vector,map,set,unordered_map,unordered_set,queue,stack:at
23.2.1/10:
Unless otherwise specified (see 23.2.4.1, 23.2.5.1, 23.3.3.4, and 23.3.6.5) all container types defined in this Clause meet the following additional requirements:
除非另有规定(见23.2.4.1,23.2.5.1,23.3.3.4和23.3.6.5),本条款中定义的所有容器类型均满足以下附加要求:
— if an exception is thrown by an insert() or emplace() function while inserting a single element, that function has no effects.
— if an exception is thrown by a push_back() or push_front() function, that function has no effects.
— no erase(), clear(), pop_back() or pop_front() function throws an exception.
— no copy constructor or assignment operator of a returned iterator throws an exception.
— no swap() function throws an exception.
— no swap() function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped.- 如果插入单个元素时insert()或emplace()函数抛出异常,则该函数不起作用。 - 如果push_back()或push_front()函数抛出异常,则该函数无效。 - 没有erase(),clear(),pop_back()或pop_front()函数抛出异常。 - 返回的迭代器的复制构造函数或赋值运算符不会抛出异常。 - 没有swap()函数抛出异常。 - 没有swap()函数使引用被交换容器元素的任何引用,指针或迭代器无效。
The quirks pointed out in the respective sections referred to above (each called Exception safety guarantees) are mostly about special against-the-wall cases like when dealing with exceptions from the contained types' hashing, comparison operations as well as throwing swap and throwing move operations.
上面提到的各个部分(每个部分称为异常安全保证)中指出的怪癖主要是关于特殊的反墙情况,例如处理包含类型的散列中的异常,比较操作以及抛出交换和抛出移动操作。
#2
8
n3376
23.2.1 General container requirements [container.requirements.general]
Paragraph 10
Unless otherwise specified (see 23.2.4.1, 23.2.5.1, 23.3.3.4, and 23.3.6.5) all container types defined in this Clause meet the following additional requirements:
— if an exception is thrown by an insert() or emplace() function while inserting a single element, that function has no effects.
— if an exception is thrown by a push_back() or push_front() function, that function has no effects.
— no erase(), clear(), pop_back() or pop_front() function throws an exception.
— no copy constructor or assignment operator of a returned iterator throws an exception.
— no swap() function throws an exception.
— no swap() function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped.
[Note: The end() iterator does not refer to any element, so it may be invalidated. —endnote]除非另有说明(参见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 containers [associative.reqmts]
23.2.4.1 Exception safety guarantees [associative.reqmts.except]
1 For associative containers, no clear() function throws an exception. erase(k) does not throw an exception unless that exception is thrown by the container’s Compare object (if any).
2 For associative containers, if an exception is thrown by any operation from within an insert or emplace function inserting a single element, the insertion has no effect.
3 For associative containers, no swap function throws an exception unless that exception is thrown by the swap of the container’s Compare object (if any).1对于关联容器,没有clear()函数抛出异常。 erase(k)不会抛出异常,除非容器的Compare对象(如果有)抛出该异常。 2对于关联容器,如果插入或插入单个元素的插入或插入函数中的任何操作抛出异常,则插入无效。 3对于关联容器,除非交换容器的Compare对象(如果有)抛出异常,否则交换函数不会抛出异常。
23.2.5 Unordered associative containers [unord.req]
23.2.5.1 Exception safety guarantees [unord.req.except]
1 For unordered associative containers, no clear() function throws an exception. erase(k) does not throw an exception unless that exception is thrown by the container’s Hash or Pred object (if any).
2 For unordered associative containers, if an exception is thrown by any operation other than the container’s hash function from within an insert or emplace function inserting a single element, the insertion has no effect.
3 For unordered associative containers, no swap function throws an exception unless that exception is thrown by the swap of the container’s Hash or Pred object (if any).
4 For unordered associative containers, if an exception is thrown from within a rehash() function other than by the container’s hash function or comparison function, the rehash() function has no effect.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); Paragraph 2
Remarks: If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T there are no effects. If an exception is thrown by the move constructor of a non-CopyInsertable T, the effects are unspecified.
备注:如果除了复制构造函数之外抛出异常,则移动构造函数,赋值运算符或T的移动赋值运算符没有任何影响。如果非CopyInsertable T的移动构造函数抛出异常,则不指定效果。
iterator erase(const_iterator first, const_iterator last); Paragraph 6
Throws: Nothing unless an exception is thrown by the copy constructor, move constructor, assignment operator, or move assignment operator of T.
抛出:除非复制构造函数,移动构造函数,赋值运算符或T的移动赋值运算符抛出异常,否则无效。
23.3.6.5 vector modifiers [vector.modifiers]
void push_back(T&& x); Paragraph 2
If an exception is thrown by the move constructor of a non-CopyInsertable T, the effects are unspecified.
如果非CopyInsertable T的移动构造函数抛出异常,则不指定效果。
iterator erase(const_iterator first, const_iterator last); Paragraph 5
Throws: Nothing unless an exception is thrown by the copy constructor, move constructor, assignment operator, or move assignment operator of T.
抛出:除非复制构造函数,移动构造函数,赋值运算符或T的移动赋值运算符抛出异常,否则无效。
#3
2
The document you've linked to, the n3337 draft standard, can be treated as official. It's the C++11 standard plus minor editorial changes.
您链接到的文件,n3337标准草案,可以视为正式文件。这是C ++ 11标准加上次要的编辑修改。
You just need to learn to read the standard, which is understandable because it's not intended to be easy reading.
你只需要学习阅读标准,这是可以理解的,因为它并不容易阅读。
To find the exception guarantees for any particular library operation, check that operation's specification for remarks and comments on exceptions. If the function is a member function then check the specification of the type for comments on exception safety and what requirements it fulfills. Then check the fulfilled requirements for exception guarantees that must be made by objects to fulfill those requirements.
要查找任何特定库操作的异常保证,请检查该操作的说明以获取有关异常的注释和注释。如果该函数是成员函数,则检查类型的规范,以获得有关异常安全性的注释以及它满足的要求。然后检查对象必须进行的异常保证的满足要求,以满足这些要求。
For generic types and algorithms also check the requirements placed on the template parameters in order to see what requirements those types have to meet in order for all the exception guarantees made by the type or algorithm or member function to hold (if the template parameters don't meet the specified requirements then using the template with those parameters has undefined behavior and none of the template's specifications apply).
对于泛型类型和算法,还要检查对模板参数的要求,以便了解这些类型必须满足哪些要求才能保持类型或算法或成员函数所做的所有异常保证(如果模板参数不合适) t满足指定的要求,然后使用具有这些参数的模板具有未定义的行为,并且不适用模板的规范)。
#1
14
Reading the standard can be scary (let's come back to the standard), but Bjarne Stroustrup has written a really nice appendix on this subject in his book 'The C++ Programming Language'. He posted this appendix at
阅读标准可能很可怕(让我们回到标准),但Bjarne Stroustrup在他的“The C ++ Programming Language”一书中写了一篇关于这个主题的非常好的附录。他把这个附录贴在了
http://www.stroustrup.com/3rd_safe0.html , at http://www.stroustrup.com/3rd_safe.pdf
http://www.stroustrup.com/3rd_safe0.html,网址:http://www.stroustrup.com/3rd_safe.pdf
It's pretty long and detailed (and well written). You may for example find section E.4 interesting, quote:
它非常详细(并且写得很好)。例如,您可以找到有趣的E.4节,引用:
E.4 Standard Container Guarantees
E.4标准集装箱保证
If a library operation itself throws an exception, it can – and does – make sure that the objects on which it operates are left in a well-defined state. For example, at() throwing out_of_range for a vector (§16.3.3) is not a problem with exception safety for the vector . The writer of at() has no problem making sure that a vector is in a well-defined state before throwing.
如果库操作本身抛出异常,它可以 - 并且确实 - 确保它所操作的对象处于明确定义的状态。例如,at()为向量抛出out_of_range(第16.3.3节)对于向量的异常安全性不是问题。 at()的作者在投掷之前确保向量处于明确定义的状态是没有问题的。
In addition, section E.4.1 states
此外,E.4.1节说明
In addition to the basic guarantee, the standard library offers the strong guarantee for a few operations that insert or remove elements.
除了基本保证之外,标准库还为插入或删除元素的一些操作提供了强有力的保证。
have a look at page 956. It contains a table of guarantees for various operations for vector, deque, list and map. In summary, all operations on those containers are either nothrow or strong, except for N - element insert into map which offers the basic guarantees.
看看第956页。它包含一个表格,用于表示矢量,双端队列,列表和地图的各种操作。总之,这些容器上的所有操作都是非常的或强大的,除了N - 元素插入到map中提供基本保证。
Note: the above text is old and does not address C++11, but should still be correct enough for most aims and purposes.
注意:上面的文字很旧,并没有解决C ++ 11,但对于大多数目的和目的来说仍然应该是正确的。
When it comes to C++11...
the standard first states, about the containers array, deque, forward_list, list, vector, map, set, unordered_map, unordered_set, queue,stack
: at
标准的第一个状态,关于容器数组,deque,forward_list,list,vector,map,set,unordered_map,unordered_set,queue,stack:at
23.2.1/10:
Unless otherwise specified (see 23.2.4.1, 23.2.5.1, 23.3.3.4, and 23.3.6.5) all container types defined in this Clause meet the following additional requirements:
除非另有规定(见23.2.4.1,23.2.5.1,23.3.3.4和23.3.6.5),本条款中定义的所有容器类型均满足以下附加要求:
— if an exception is thrown by an insert() or emplace() function while inserting a single element, that function has no effects.
— if an exception is thrown by a push_back() or push_front() function, that function has no effects.
— no erase(), clear(), pop_back() or pop_front() function throws an exception.
— no copy constructor or assignment operator of a returned iterator throws an exception.
— no swap() function throws an exception.
— no swap() function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped.- 如果插入单个元素时insert()或emplace()函数抛出异常,则该函数不起作用。 - 如果push_back()或push_front()函数抛出异常,则该函数无效。 - 没有erase(),clear(),pop_back()或pop_front()函数抛出异常。 - 返回的迭代器的复制构造函数或赋值运算符不会抛出异常。 - 没有swap()函数抛出异常。 - 没有swap()函数使引用被交换容器元素的任何引用,指针或迭代器无效。
The quirks pointed out in the respective sections referred to above (each called Exception safety guarantees) are mostly about special against-the-wall cases like when dealing with exceptions from the contained types' hashing, comparison operations as well as throwing swap and throwing move operations.
上面提到的各个部分(每个部分称为异常安全保证)中指出的怪癖主要是关于特殊的反墙情况,例如处理包含类型的散列中的异常,比较操作以及抛出交换和抛出移动操作。
#2
8
n3376
23.2.1 General container requirements [container.requirements.general]
Paragraph 10
Unless otherwise specified (see 23.2.4.1, 23.2.5.1, 23.3.3.4, and 23.3.6.5) all container types defined in this Clause meet the following additional requirements:
— if an exception is thrown by an insert() or emplace() function while inserting a single element, that function has no effects.
— if an exception is thrown by a push_back() or push_front() function, that function has no effects.
— no erase(), clear(), pop_back() or pop_front() function throws an exception.
— no copy constructor or assignment operator of a returned iterator throws an exception.
— no swap() function throws an exception.
— no swap() function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped.
[Note: The end() iterator does not refer to any element, so it may be invalidated. —endnote]除非另有说明(参见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 containers [associative.reqmts]
23.2.4.1 Exception safety guarantees [associative.reqmts.except]
1 For associative containers, no clear() function throws an exception. erase(k) does not throw an exception unless that exception is thrown by the container’s Compare object (if any).
2 For associative containers, if an exception is thrown by any operation from within an insert or emplace function inserting a single element, the insertion has no effect.
3 For associative containers, no swap function throws an exception unless that exception is thrown by the swap of the container’s Compare object (if any).1对于关联容器,没有clear()函数抛出异常。 erase(k)不会抛出异常,除非容器的Compare对象(如果有)抛出该异常。 2对于关联容器,如果插入或插入单个元素的插入或插入函数中的任何操作抛出异常,则插入无效。 3对于关联容器,除非交换容器的Compare对象(如果有)抛出异常,否则交换函数不会抛出异常。
23.2.5 Unordered associative containers [unord.req]
23.2.5.1 Exception safety guarantees [unord.req.except]
1 For unordered associative containers, no clear() function throws an exception. erase(k) does not throw an exception unless that exception is thrown by the container’s Hash or Pred object (if any).
2 For unordered associative containers, if an exception is thrown by any operation other than the container’s hash function from within an insert or emplace function inserting a single element, the insertion has no effect.
3 For unordered associative containers, no swap function throws an exception unless that exception is thrown by the swap of the container’s Hash or Pred object (if any).
4 For unordered associative containers, if an exception is thrown from within a rehash() function other than by the container’s hash function or comparison function, the rehash() function has no effect.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); Paragraph 2
Remarks: If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T there are no effects. If an exception is thrown by the move constructor of a non-CopyInsertable T, the effects are unspecified.
备注:如果除了复制构造函数之外抛出异常,则移动构造函数,赋值运算符或T的移动赋值运算符没有任何影响。如果非CopyInsertable T的移动构造函数抛出异常,则不指定效果。
iterator erase(const_iterator first, const_iterator last); Paragraph 6
Throws: Nothing unless an exception is thrown by the copy constructor, move constructor, assignment operator, or move assignment operator of T.
抛出:除非复制构造函数,移动构造函数,赋值运算符或T的移动赋值运算符抛出异常,否则无效。
23.3.6.5 vector modifiers [vector.modifiers]
void push_back(T&& x); Paragraph 2
If an exception is thrown by the move constructor of a non-CopyInsertable T, the effects are unspecified.
如果非CopyInsertable T的移动构造函数抛出异常,则不指定效果。
iterator erase(const_iterator first, const_iterator last); Paragraph 5
Throws: Nothing unless an exception is thrown by the copy constructor, move constructor, assignment operator, or move assignment operator of T.
抛出:除非复制构造函数,移动构造函数,赋值运算符或T的移动赋值运算符抛出异常,否则无效。
#3
2
The document you've linked to, the n3337 draft standard, can be treated as official. It's the C++11 standard plus minor editorial changes.
您链接到的文件,n3337标准草案,可以视为正式文件。这是C ++ 11标准加上次要的编辑修改。
You just need to learn to read the standard, which is understandable because it's not intended to be easy reading.
你只需要学习阅读标准,这是可以理解的,因为它并不容易阅读。
To find the exception guarantees for any particular library operation, check that operation's specification for remarks and comments on exceptions. If the function is a member function then check the specification of the type for comments on exception safety and what requirements it fulfills. Then check the fulfilled requirements for exception guarantees that must be made by objects to fulfill those requirements.
要查找任何特定库操作的异常保证,请检查该操作的说明以获取有关异常的注释和注释。如果该函数是成员函数,则检查类型的规范,以获得有关异常安全性的注释以及它满足的要求。然后检查对象必须进行的异常保证的满足要求,以满足这些要求。
For generic types and algorithms also check the requirements placed on the template parameters in order to see what requirements those types have to meet in order for all the exception guarantees made by the type or algorithm or member function to hold (if the template parameters don't meet the specified requirements then using the template with those parameters has undefined behavior and none of the template's specifications apply).
对于泛型类型和算法,还要检查对模板参数的要求,以便了解这些类型必须满足哪些要求才能保持类型或算法或成员函数所做的所有异常保证(如果模板参数不合适) t满足指定的要求,然后使用具有这些参数的模板具有未定义的行为,并且不适用模板的规范)。