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);
}