抛出交换成员实现是否可以?

时间:2011-10-05 12:38:09

标签: c++ swap exception-safe copy-and-swap exception-safety

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

但是,如果因为我的班级使用不提供交换操作的第三方类成员而无法提供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 swap无法进行无抛出,因此交换可能会失败。

注意:对于罕见的第三方课程,使用智能ptr(pimpl)是一个选项,但是 -

注意:CString是一个很好的例子,因为他的正确思想(?)中的任何人都会开始通过pimpl(智能ptr)开始持有像CString这样的概念上简单且无处不在的类的所有成员,因为那真的看起来很糟糕 - 而且另一方面,没有(短期到中期)机会将CString修改为允许完全无投掷交换。

所以,如果你无法帮助它,可以使用潜在的抛出交换成员函数吗? (或者你知道解决这个难题的方法吗?)

编辑:并且:抛出交换成员是否可以使用复制和交换习惯用法提供基本保证,如果不是强有力的保证?

3 个答案:

答案 0 :(得分:3)

  

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

没有任何内容错误的具有可能抛出的swap函数,但要注意,如果没有swap中的强异常保证,它就不可能用于提供异常安全性,也就是说,它只能用作swap(也就是说,忘记该特定类的复制和交换习惯用法,作为提供强大异常保证的方式......但你可以仍然使用它来减少代码量 - 并记录它不是异常安全的)

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

答案 1 :(得分:2)

投掷swap没有任何内在错误,它只是没有投掷版本。

复制和交换习惯用法不需要​​swap是无抛出的,以便提供强大的异常保证。 swap只需要提供强有力的例外保证。

难点在于,如果无法提供无投保证,则很可能无法提供强烈的例外保证。使用临时和三个副本进行天真交换只提供基本保证,除非复制操作提供无投掷保证,在这种情况下交换也是无投掷。

答案 2 :(得分:-2)

你可以轻松地让它变得更好:

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(...)
    {
    }
}

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