6

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 ???
}
4

2 回答 2

16

C++ 标准保证 std::swap 不会抛出异常。

不,它没有。见 20.2.2 或参考。两个重载有两个 noexcept 规范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是错误的,因此实例化std::swap<A>没有不抛出保证。从这个交换中捕获异常是完全合法的。

于 2013-01-30T10:23:09.053 回答
10

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

从 20.2.2/1 开始:

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

备注:noexcept 里面的表达式等价于:

 is_nothrow_move_constructible<T>::value &&
 is_nothrow_move_assignable<T>::value
于 2013-01-30T10:27:18.503 回答