对象交换过程不可抛出异常
7.10 ID_throwInSwap
两个对象在交换(swap)过程中,每个对象的状态都是不完整的,如果在交换中途抛出异常,对象将处于错误的状态。
注意,交换是保证异常安全的重要手段,不抛出异常是基本要求,详见 ID_exceptionUnsafe。标准库中存在大量与交换相关的接口和算法,如果抛出异常也会使标准库无法按约定工作,所有交换相关的函数均应标记为 noexcept。
示例:
struct T {
string m;
void swap(T& a) { // Non-compliant
string tmp = m;
m = a.m;
a.m = tmp; // If allocation fails, both ‘a’ and *this will be incorrect
}
};
例中通过复制的方式交换字符串是不符合要求的,如果内存分配失败,被交换的两个对象都将处于错误状态。
应使用字符串类提供的交换函数:
struct T {
string m;
void swap(T& a) noexcept { // Compliant
m.swap(a.m);
}
};
std::string::swap 会直接交换字符串对象的成员,避免内存分配和复制,从而避免抛出异常。