4

编写类时的一般准则(使用复制和交换习惯用法)是提供一个非抛出交换成员函数。(Effective C++,第 3 版,第 25 条和其他资源)

但是,如果因为我的班级使用不提供交换操作的第 3 方班级成员而无法提供 nothrow 保证怎么办?

// Warning: Toy code !!!

class NumberBuffer {
public:
    ...
    void swap(NumberBuffer& rhs);

public:
    float* m_data;
    size_t m_n;
    CString m_desc;
};

void swap(NumberBuffer& lhs, NumberBuffer& rhs) {
    lhs.swap(rhs);
}

void NumberBuffer::swap(NumberBuffer& rhs) {
    using std::swap;
    swap(m_data, rhs.m_data);
    swap(m_n, rhs.m_n);
    swap(m_desc, rhs.m_desc); // could throw if CString IsLocked and out-of-mem
}

CString 交换不能不抛出,因此交换失败的可能性很小。

注意:对于罕见的第 3 方课程,可以选择使用智能 ptr (pimpl),但是--

注意:CString 是一个很好的例子,因为他头脑正常(?)的人不会开始通过 pimpl(智能 ptr)持有概念上简单且无处不在的类的所有成员,例如 CString,因为这看起来真的很可怕——另一方面,没有(短期到中期)机会来修改 CString 以允许完全不抛出交换。

那么,如果你不能帮助它,是否可以有一个潜在的抛出交换成员函数?(或者你知道解决这个难题的方法吗?)

编辑:并且:如果不是强保证,是否可以将抛出交换成员与复制和交换习语一起使用以提供基本保证?

4

3 回答 3

3

那么,如果你不能帮助它,是否可以有一个潜在的抛出交换成员函数?(或者你知道解决这个难题的方法吗?)

拥有一个可能抛出异常的函数本身并没有,但是请注意,如果没有 中的强异常保证,它就不可能用于提供异常安全性,也就是说,它只能用作(也就是说,忘记该特定类的复制和交换习语作为提供强大异常保证的一种方式......但您仍然可以使用它来减少代码量 - 并记录它不是异常安全的)swapswapswap

或者,您可以将 移动CString到提供不抛出swap(或至少是强异常保证)的智能指针中,这不是一个好的解决方案,但它至少是异常安全的。最后,您可以完全摆脱CString使用任何其他提供所需内容并提供无抛出交换操作的字符串库。

于 2011-10-05T12:48:14.077 回答
2

throwing 本质上没有任何问题swap,它只是不如 no-throw 版本有用。

swap为了提供强大的异常保证,复制和交换习语不需要是 no-throw。swap只需要提供强大的异常保证。

难点在于,如果不能提供不抛保证,也很可能不能提供强例外保证。使用临时和三个副本的朴素交换仅提供基本保证,除非复制操作提供不抛出保证,在这种情况下交换也是不抛出。

于 2011-10-05T13:36:45.143 回答
-2

你可以很容易地让它nothrow:

void NumberBuffer::swap(NumberBuffer& rhs) throw()
{
    try
    {
        std::swap(m_desc, rhs.m_desc);   //could throw
        std::swap(m_data, rhs.m_data);
        std::swap(m_n, rhs.m_n);
    }
    catch(...)
    {
    }
}

当然,这不是问题的真正解决方案,但现在你至少得到了你的非抛出交换;)

于 2011-10-05T12:46:37.800 回答