编写类(使用复制和交换习惯用法)时的一般准则是提供非抛出交换成员函数。 (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修改为允许完全无投掷交换。
所以,如果你无法帮助它,可以使用潜在的抛出交换成员函数吗? (或者你知道解决这个难题的方法吗?)
编辑:并且:抛出交换成员是否可以使用复制和交换习惯用法提供基本保证,如果不是强有力的保证?
答案 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(...)
{
}
}
当然,这不是问题的真正解决方案,但现在你至少得到了非投掷交换;)