可以抛出交换成员实现吗?
编写类(使用复制和交换习惯用法)时的一般准则是提供一个非抛出交换成员函数。 (Effective C++,第 3 版,第 25 项 和其他资源)
但是,如果我无法提供没有抛出保证,因为我的类使用不提供交换操作的第 3 方类成员?
// 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 以允许完全禁止 -扔 交换。
那么,如果你无能为力的话,拥有一个可能会抛出异常的交换成员函数是否可以? (或者您知道解决这个难题的方法吗?)
编辑:并且:抛出交换成员是否可以与复制和交换习惯用法一起使用,以提供基本保证(如果不是强保证)?
The general guideline when writing classes (using the copy-and-swap idiom) is to provide a non throwing swap member function. (Effective C++, 3rd edition, Item 25 and other resources)
However, what if I cannot provide the nothrow guarantee because my class uses a 3rd party class member that doesn't provide a swap operation?
// 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 cannot be made no-throw, so there's the off chance the swap could fail.
Note: For rare 3rd party classes, using a smart ptr (pimpl) would be an option, but --
Note: CString is a good example as noone in his right mind (?) would start holding all members of a conceptually simple and ubiquitous class like CString via pimpl (smart ptr) because that would really look horrible -- and on the other hand, there's no (short to mid-term) chance to get the CString modified to allow fully no-throw swap.
So, is it OK to have a potentially throwing swap member function if you can't help it? (Or do you know ways around this conundrum?)
Edit: And: Can a throwing swap member be used with the copy-and-swap idiom to provide the basic guarantee if not the strong guarantee?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
拥有可能引发异常的
swap
函数本质上没有什么错误,但要注意,如果没有 中的强异常保证, code>swap,它不可能用于提供异常安全,也就是说,它只能用作swap
(也就是说,忘记复制和交换的习惯用法)特定类作为提供强异常的一种方式保证...但您仍然可以使用它来减少代码量 - 并且记录它不是异常安全的)或者,您可以将
CString
移动到提供 no- throwswap
(或者至少是强异常保证),不是一个好的解决方案,但它至少是异常安全的。最后,您可以使用任何其他字符串库来完全摆脱CString
,该库可以提供您需要的任何内容并提供无抛出交换操作。There is nothing inherently wrong with having a
swap
function that can potentially throw, but beware that without the strong exception guarantee inswap
, it cannot possibly be used to provide exception safety, that is, it can only be used asswap
(that is, forget about the copy-and-swap idiom for that particular class as a way of providing the strong exception guarantee... but you can still use it to reduce the amount of code --and document that it is not exception safe)Alternatively, you can move the
CString
into a smart pointer that offers a no-throwswap
(or at the very least the strong exception guarantee), not a nice solution, but it will at least be exception safe. Lastly, you can move away fromCString
altogether by using any other string library that provides whatever you need and offers a no-throw swap operation.抛出交换本质上没有任何问题,它只是不如不抛出版本有用。
复制和交换惯用法不需要将
swap
设为 no- throw 来提供强大的异常保证。swap
只需要提供强有力的异常保证。困难在于,如果不能提供不抛出保证,那么也很可能不能提供强异常保证。使用临时和三个副本的朴素交换仅提供基本保证,除非复制操作提供不抛出保证,在这种情况下交换也是不抛出的。
There's nothing inherently wrong with a throwing
swap
, it is just less useful than a no-throw version.The copy and swap idiom doesn't need
swap
to be no-throw in order to provide the strong exception guarantee.swap
needs only to provide the strong exception guarantee.The difficulty is that if the no-throw guarantee cannot be provided, it is also likely that the strong exception guarantee cannot be provided. Naive swapping using a temporary and three copies only provides the basic guarantee unless the copying operation provides the no-throw guarantee, in which case swap is also no-throw.
您可以轻松地使其不抛出:
当然,这并不是问题的真正解决方案,但现在您至少得到了不抛出交换;)
You can easily make it nothrow:
Of course, this is no real solution to the problem, but now you at least got your non-throwing swap ;)