C++迭代程序异常安全
C++ Iterator Exception Safety
我在异常安全和STL容器/迭代器方面遇到问题。
出于某种原因,我假设简单容器的迭代器
std::vector<POD Type>
在对它(或deref.it)执行算术运算时,只要你保持在区间[begin(),end())内,就不会抛出异常。我试图在标准中查找它(使用N3337),但我发现没有给出这样的nothrow保证(但可能我错过了什么!)。另请参阅:可能STL迭代器方法抛出异常
到目前为止,我写了一些通常会被破坏的代码,考虑到即使对于具有合理元素类型的简单容器,也没有所谓的nothrow保证。
例如,以下内容可能仍然引发异常(其中c是std::vector实例):
for(... i = c.begin(); i != c.end(); ++i) { /* do something here - guaranteed to not throw. */ }
但这会在不同的STD库中引发异常安全和程序稳定性问题,因为据我所知,您必须了解迭代器操作的实现。
例如,以Boost.Graph的邻接列表的clear()函数为例(Boost中还有更多这样的例子),并假设容器m_顶点是一个类似std::vector的std序列容器。
inline void clear() {
for (typename StoredVertexList::iterator i = m_vertices.begin(); // begin() and copy assignement does not throw (according to the STD)
i != m_vertices.end(); ++i) // ++i and operator != () might throw
delete (stored_vertex*)*i; // *i might throw
m_vertices.clear(); // will not throw (nothrow per Definition of the STD)
m_edges.clear(); // same
}
应该保证此函数不会抛出,因为它是在相邻列表的析构函数<…>中调用的假设没有clear()函数抛出是合理的,尽管我在Boost.Graph.的文档中没有发现任何异常安全保证
我希望你能对这个特殊的安全问题有所了解,并向我展示我在这里缺少的东西。特别是对于什么样的迭代器,算术运算和去引用实际上不是抛出的,以及在哪里定义了这样的保证。
谢谢!
来自C++STD纸张N3337
23.2.1:10)
除非另有规定(见23.2.4.1、23.2.5.1、23.3.3.4和23.3.6.5),否则本规范中定义的所有集装箱类型条款满足以下附加要求:
--如果insert()或template()函数在插入单个元素时引发异常,则函数没有任何效果。
--如果pushback()或pushfront()函数抛出异常,则该函数没有任何效果。
--没有erase()、clear()、pop_back()或pop_front()函数抛出异常。
--返回迭代器的复制构造函数或赋值运算符都不会引发异常。
--没有swap()函数抛出异常。
--没有swap()函数使引用正在交换的容器。
[注意:end()迭代器没有引用任何元素,因此它可能是无效--结束注释]
只有宽合约(即不可能失败的操作)才没有抛出保证。所有迭代器操作都有狭窄的约定(即,它们有一些前提条件),因此,当不满足前提条件时,可能会以任意方式失败。因此,它们没有任何异常保证,因为未定义的行为前提条件不满足可能会导致给定的实现抛出异常。假设先决条件得到满足,并且行为不包括抛出任何异常,则各个迭代器操作的行为都得到了很好的定义:迭代器运算的行为在需求表中定义。
也就是说,总的来说,你应该期望所有的操作都有可能首先抛出。为了从异常中进行正确的恢复:然而,有时有必要知道特定的函数不会抛出,否则恢复可能会失败,某些相当基本的操作(如交换两个内置类型的对象)被定义为不抛出。
- C++代码中的异常安全
- 编写"anti-lack of memory"异常安全代码
- std:string::substr 异常安全吗?
- 如何以异常安全的方式使用放置新?
- 通过引用从 c++ 函数异常返回对象是否安全
- 异常安全服务器
- 实现 std::vector::p ush_back 强异常安全
- 标准::unique_ptr和异常安全
- 如何使用QThreads使无锁生产者-消费者线程交换更加异常安全
- 使功能异常安全
- 与构造函数参数相关的异常安全的习语
- uninitialized_copy() 异常安全吗?
- 为什么我们需要 RAII 来解决异常安全问题
- 异常安全构造函数
- 关于 swap() 操作的异常安全 - 这有什么问题?
- std::vector::擦除异常安全
- 异常安全 - 用于可靠回滚对象状态的模式
- 异常安全的 for 循环
- 异常安全代码和移动语义
- 向量::插入的异常安全保证是什么?