可以抛出交换成员实现吗?

发布于 2024-12-07 22:24:02 字数 1054 浏览 0 评论 0原文

编写类(使用复制和交换习惯用法)时的一般准则是提供一个非抛出交换成员函数。 (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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

站稳脚跟 2024-12-14 22:24:02

那么,如果你无能为力的话,有一个可能会抛出异常的交换成员函数可以吗? (或者您知道解决这个难题的方法吗?)

拥有可能引发异常的 swap 函数本质上没有什么错误,但要注意,如果没有 中的强异常保证, code>swap,它不可能用于提供异常安全,也就是说,它只能用作 swap (也就是说,忘记复制和交换的习惯用法)特定类作为提供强异常的一种方式保证...但您仍然可以使用它来减少代码量 - 并且记录它不是异常安全的)

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

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?)

There is nothing inherently wrong with having a swap function that can potentially throw, but beware that without the strong exception guarantee in swap, it cannot possibly be used to provide exception safety, that is, it can only be used as swap (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-throw swap (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 from CString altogether by using any other string library that provides whatever you need and offers a no-throw swap operation.

眼泪都笑了 2024-12-14 22:24:02

抛出交换本质上没有任何问题,它只是不如不抛出版本有用。

复制和交换惯用法不需要​​将 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.

神经大条 2024-12-14 22:24:02

您可以轻松地使其不抛出:

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

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

You can easily make it 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(...)
    {
    }
}

Of course, this is no real solution to the problem, but now you at least got your non-throwing swap ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文