6

スローしないスワップ イディオムを実装する場合、使用する必要がありますthrow()か?

namespace A
{
   struct B
   {
     void swap( B& other ) throw()
     { /* fancy stuff that doesn't throw */ }
   };

   void swap( B& lhs, B& rhs ) throw()
   { lhs.swap(rhs); }
}

namespace std
{
   template<>
   void swap( A::B& lhs, A::B& rhs ) throw()
   { lhs.swap(rhs); }
}

throw()特にの専門化に仕様を載せるのが気になりstd::swapます。

おまけの質問:
C++0x のnoexceptキーワードを使用する場合、答えは異なりますか?

4

3 に答える 3

4

C++03ではそこに置くことができますが、派手なものがスローされないことが本当なら、それは基本的に単なるドキュメントです. 関数に around 呼び出しに相当するものを追加することで、パフォーマンスに影響する場合としない場合がありますtry / catch(...) { std::unexpected(); }。パフォーマンスに影響を与えずに実行できるかどうかは、実装次第です。

noexcept C++0x で演算子(5.3.7)を使用する予定がある場合、演算子が「正しい」答えを返すように、スローしない例外指定を使用する価値があります。演算子の目的はよくわかりませんがnoexcept、たとえば、何かがスローされないときにより効率的になるアルゴリズムなど、巧妙な一般的な使用法がある場合は、関数を非スローとしてマークすることが必要になると思います。投げて、利益が何であれ得るために。

例えば:

void foo() noexcept;
void bar();

template <void(*FUNC)()>
void generic_thing() {
    if (noexcept(FUNC()) {
        // this won't throw, perhaps we can somehow take advantage of that
        FUNC();
    } else {
        // this might throw
        FUNC();
    }
}

古いスタイルの例外仕様 ( dynamic-exception-specification ) は、C++0x では非推奨です (C++03 では無意味です)。

于 2010-11-13T00:25:53.067 に答える
3

それは良い考えではありません。その理由は、最初に導入されたthrow()ものである正確さを強制することが不可能な場合があることを標準が知っているからです。throw()特に、インスタンス化に応じて例外がスローされる場合とスローされない場合があるテンプレートの場合、テンプレートのインスタンス化なしでは正確さをチェックすることは不可能です。したがって、標準では、コンパイラが例外指定子を強制する必要さえありません。実際、実装が式を拒否することを禁止しています。「実行時に、含まれている関数が許可しない例外をスローするか、スローする可能性があるという理由だけで」(15.4/11)。

throw()ドキュメント以外の効果がない場合は、コメント アウトする必要があります。このようにして、少なくとも人間の観察者を誤解させるリスクはありません。

の場合noexceptはまったく異なります。noexcept別の理由で存在するようになります。パフォーマンスのこと。コンパイラに例外がスローされないことを保証できる場合、コンパイラはいくつかの最適化を実行できます。ただし、チェックは自分で行う必要がありますしたがって、実際にswap()スローしない場合 (スローすべきではありません。それがその存在理由です)、指定することnoexceptをお勧めします。

于 2010-11-13T00:32:59.170 に答える
1

現実的には、いいえ。例外仕様は素晴らしいアイデアでしたが、実際には、コードの大部分を助ける以上に妨げていました。誰もそれらを使用しておらず、C++0x では推奨されていません。最新の C++ で例外仕様を記述することに時間をかけないでください。

于 2010-11-13T00:29:55.673 に答える