[英]std::vector::erase exception safety
我已经读过std :: vector擦除方法仅在已知类型由于强大的异常安全性而不会发出异常的情况下才使用移动操作。 其他评论是,擦除方法根据元素构造函数是否抛出来保证基本的或没有抛出异常的安全性。 我无法在C ++ 11草案中阐明这一点。 我做了测试,它显示了基本的异常安全保证,它还使用了未标记为noexcept的move构造函数。 我忽略了什么吗? 什么是对的 ?
表100-第23.2.3节[sequence.reqmts]中的序列容器要求说:
a.erase(q)
要求:对于
vector
和deque
,T
应为MoveAssignable
。
这意味着该实现只能对T
进行破坏或移动分配操作,而不能对T
调用任何操作。 请注意,如果实现中移动分配了T
,则不能保证将调用移动分配操作符。 例如, T
可能没有移动分配运算符,因此在这种情况下,可以调用副本分配运算符。 但是,该实现不允许复制分配T
,只能移动分配T
*i = std::move(*j); // implementation can do this
*i = *j; // implementation can not do this
此外,23.3.6.5矢量修饰符[vector.modifiers]表示以下内容:
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
抛出:无。如果有异常的拷贝构造函数抛出,移动构造函数,赋值运算符,或移动的赋值操作符
T
。
我必须承认,我在读这篇文章时叹了口气。 显然这里有一个小缺陷。 不允许此操作形成直接构造T
任何表达式。 也许有人将其构造为T
的赋值运算符内的实现细节,但这与本规范无关。 问题在于此表达式是否抛出:
*i = std::move(*j); // implementation can do this. Will it throw?
如果该表达式(其中i
和j
是引用T
迭代器)没有抛出,则vector::erase
具有无抛出保证。 否则, vector::erase
具有基本的异常安全保证。
请注意,对于此操作,如果is_nothrow_move_assignable<T>::value
为false,则不允许实现回退到副本分配。 此类逻辑存在于其他vector
操作(例如push_back
,但此处不存在。
还要注意同一部分的复杂度规范:
复杂性:
T
的析构函数被称为等于擦除的元素数的次数,但是T
的移动分配运算符被称为等于被擦除的元素之后向量中的元素数的次数。
重述:如果擦除以向量的结尾结尾的一系列元素,则将执行零移动分配,并且移动分配是唯一可能抛出的事件。 因此,即使is_nothrow_move_assignable<T>::value
为false,如果您要在最后进行擦除,也可以获得无掷保证。
23.3.6.5抛出:除非T的副本构造函数,move构造函数,赋值运算符或move赋值运算符抛出异常,否则什么都不会发生。
只要您的实现符合此要求,它就可以按照需要实施擦除。 据我所知,没有隐式异常安全保证。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.