C++ 关于swap()操作的异常安全-什么';这有什么不对吗?
我一直在读C++ 关于swap()操作的异常安全-什么';这有什么不对吗?,c++,exception,exception-handling,exception-safety,C++,Exception,Exception Handling,Exception Safety,我一直在读swap()操作,例如: template<class T> void swap (T &a, T &b) { T temp (a); a = b; b = temp; } 模板 无效掉期(T&a、T&b) { 温度(a); a=b; b=温度; } 在我们处理异常安全时存在问题 有什么不对劲吗? 此外,我们如何解决这个问题 在一般实现中,假设T的任何操作都可以抛出,则无法提供强异常保证,这意味着在发生异常时保持操作前的状态。即使T上的每个操
swap()
操作,例如:
template<class T>
void swap (T &a, T &b)
{
T temp (a);
a = b;
b = temp;
}
模板
无效掉期(T&a、T&b)
{
温度(a);
a=b;
b=温度;
}
在我们处理异常安全时存在问题
有什么不对劲吗?
此外,我们如何解决这个问题 在一般实现中,假设
T
的任何操作都可以抛出
,则无法提供强异常保证,这意味着在发生异常时保持操作前的状态。即使T
上的每个操作都提供了强大的异常保证:
template<class T>
void swap (T &a, T &b)
{
T temp (a); // [1]
a = b; // [2]
b = temp; // [3]
}
因为复制指针不能抛出,上面的
swap
提供了无抛出保证,如果您总是按照上面的模式实现swap
(使用std::swap;
,然后是对swap
的非限定调用)它将被ADL视为比std::swap更好的匹配,丹尼尔当然是对的
但您不应该忘记,在异常安全方面,交换通常被认为是解决方案的一部分(“复制和交换习惯用法”),而不是问题所在。剩下的问题是,如果您采用这种习惯用法,您必须确保swap可能调用的复制构造函数不会抛出异常,这是Daniel解释的原因
请参阅:已解释了异常的来源 但是您可以通过将参数强制转换为
无符号字节*
并逐字节交换到sizeof(T)
来避免异常。请注意,这不会调用对象上的任何构造函数或析构函数,在进行自引用时可能会违反某些先决条件(当互换后a
指向b
时a
将指向a
)
D标准库中的swap就是这样做的(在它检查了自引用之后)+1我打算写同样的东西。到的链接将是一个帮助,对于那些想详细了解基于契约的异常安全性的人非常有用。
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);
}