我继续读这个swap()操作,像这样:
template<class T> void swap (T &a,T &b) { T temp (a); a = b; b = temp; }
当我们处理异常安全时,是有问题的.
这是怎么了?
此外,我们如何解决呢?
解决方法
在一般实现中,假设T的任何操作都可以抛出,您不能提供强大的异常保证,这意味着在异常事件发生之前将状态与操作之前完全一致.即使T上的每个操作都提供了强大的异常保证:
template<class T> void swap (T &a,T &b) { T temp (a); // [1] a = b; // [2] b = temp; // [3] }
如果[1]抛出,输入将保持不变,这是很好的.如果[2]抛出,并假设强大的异常保证,值仍然不变,这是很好的.但是如果[3]抛出,则已经被修改,这意味着在异常传播到堆栈之后,调用者将被保留一个既不是原始状态也不是最终状态的状态.
编辑:此外,我们如何解决呢?
没有一般的解决方案.但在大多数情况下,您可以为您的类型提供一个异常安全交换操作.考虑通过使用三个指针(开始,结束,容量)内部来管理其状态的向量< T> ;.上面的一般交换可以抛出(无法分配,内部T的构造函数可能会抛出...),但提供无投掷交换实现是微不足道的:
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); }
因为复制指针不能抛出,所以上面的swap提供了无抛出保证,如果你总是按照上面的模式实现交换(使用std :: swap;后面是不合格的调用来进行交换),它将被ADL所接受比std :: swap更好的匹配.