如果传递到 std::swap 的对象在交换过程中引发异常怎么办?

What if an object passed into std::swap throws an exception during swapping?

本文关键字:交换 过程中 怎么办 异常 对象 std swap 如果      更新时间:2023-10-16

C++标准保证std::swap不会抛出异常。但是,如果要交换的对象在交换期间引发异常怎么办?接下来,调用方应如何查找已发生的异常?呼叫者应采取哪些措施?

PS:构造函数引发异常是很常见的。

struct A
{
    A(const A&)
    {
        throw 1;
    }
    A& operator =(const A&)
    {
        throw 2;
        return *this;
    }
};
int main()
{
    A a1, a2;
    std::swap(a1, a2); // An exception happened, but the caller doesn't know.
    // How to do here ???
}

C++标准保证 std::swap 不会引发异常。

不,它没有。请参阅 20.2.2 或参考。对于这两种std::swap重载,有两种例外规范:

template<class T> void swap(T& a, T& b)
noexcept(noexcept(
    std::is_nothrow_move_constructible<T>::value &&
    std::is_nothrow_move_assignable<T>::value
))
template<class T, size_t N>
void swap(T (&a)[N], T (&b)[N])    
noexcept(noexcept(swap(*a, *b)))

当这些条件不满足时,std::swap可以投掷,你可以接住它。


对于您提供的类,谓词 std::is_nothrow_move_constructiblestd::is_nothrow_move_assignable 为 false,因此实例化std::swap<A>没有不抛出保证。从此交换中捕获异常是完全合法的。

该标准通常不保证交换不会抛出。

从 20.2.2/1:

模板无效交换(T&a,T&b)noexcept(见下文);

备注:noexcept 中的表达式等效于:

 is_nothrow_move_constructible<T>::value &&
 is_nothrow_move_assignable<T>::value