4

(copy-and-swap イディオムを使用して) クラスを作成するときの一般的なガイドラインは、スローしないスワップ メンバー関数を提供することです。( Effective C++、第 3 版、項目 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 スワップを非スローにすることはできないため、スワップが失敗する可能性は低いです。

注: まれなサード パーティ クラスでは、スマート ptr (pimpl) を使用することもできますが、 -

注: CString は良い例です。彼の正気 (?) の誰も、pimpl (smart ptr) を介して CString のような概念的に単純でユビキタスなクラスのすべてのメンバーを保持し始めることはありません。 CString を変更して完全にノースロー スワップを許可する (短期から中期) チャンスはありません。

それで、あなたがそれを助けることができないなら、スワップメンバー関数をスローする可能性があっても大丈夫ですか? (または、この難問を回避する方法を知っていますか?)

編集:そして:強力な保証ではない場合、基本的な保証を提供するために、スロースワップメンバーをコピーアンドスワップイディオムで使用できますか?

4

3 に答える 3

3

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.

于 2011-10-05T12:48:14.077 に答える
2

投げることには本質的に何も悪いswapことはありません、それは投げないバージョンよりも有用性が低いだけです。

強力な例外保証を提供するために、コピーとスワップのイディオムswapをスローする必要はありません。swap強力な例外保証を提供するだけで済みます。

難点は、ノースロー保証が提供できない場合、強力な例外保証も提供できない可能性が高いことです。一時的な3つのコピーを使用したナイーブスワップは、コピー操作でスローなしの保証が提供されない限り、基本的な保証のみを提供します。この場合、スワップもスローなしです。

于 2011-10-05T13:36:45.143 に答える
-2

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

于 2011-10-05T12:46:37.800 に答える