JAN*_*JAN 10 c++ exception-handling exception exception-safety
我继续阅读该swap()操作,例如:
template<class T>
void swap (T &a, T &b)
{
T temp (a);
a = b;
b = temp;
}
Run Code Online (Sandbox Code Playgroud)
当我们处理异常安全时会出现问题.
它有什么问题?此外,我们如何解决它?
Dav*_*eas 22
在一般实现中,假设Tcan的任何操作throw,您都不能提供强异常保证,这意味着在异常事件的操作之前完全保留状态.即使每个操作都T提供强大的异常保证:
template<class T>
void swap (T &a, T &b)
{
T temp (a); // [1]
a = b; // [2]
b = temp; // [3]
}
Run Code Online (Sandbox Code Playgroud)
如果[1]抛出,则输入保持不变,这很好.如果[2]抛出,并且假设强异常保证,则值仍未触及,这是好的.但是如果抛出的是[3],a则已经被修改,这意味着在异常传播到堆栈之后,调用者将留下既不是原始状态也不是最终状态的状态.
编辑:此外,我们如何解决它?
没有通用的解决方案.但在大多数情况下,您可以为swap类型提供异常安全操作.考虑一个vector<T>,在内部通过使用三个指针(管理它的状态begin,end,capacity).swap上面的一般可以抛出(无法分配,内部的构造函数T可能会抛出......),但提供一个无抛出的swap实现是微不足道的:
template <typename T>
class vector {
T *b,*e,*c;
public:
void swap( vector<T>& rhs ) {
using std::swap;
swap( b, rhs.b );
swap( e, rhs.e );
swap( c, rhs.c );
}
//...
};
template <typename T>
void swap( vector<T>& lhs, vector<T>& rhs ) {
lhs.swap(rhs);
}
Run Code Online (Sandbox Code Playgroud)
因为指针的复制不能抛出,所以swap上面提供了无抛出保证,如果你总是swap按照上面的模式实现(using std::swap;接着swap是非限定的调用),它将被ADL选中作为更好的匹配std::swap.