23

swap今日、C++ で例外をスローすることは許可されていないことを知りました。

また、以下も例外をスローできないことも知っています。

  • デストラクタ
  • プリミティブ型の読み取り/書き込み

他にもありますか?
それとも、スローしない可能性があるすべてを言及したある種のリストがありますか?
(明らかに、標準自体よりも簡潔なものです。)

4

3 に答える 3

17

cannotshould notには大きな違いがあります。プリミティブ型の操作は、標準ライブラリおよび/または他の多くのライブラリの多くの操作を含む、多くの関数およびメンバー関数をスローできません。

should notでは、デストラクタとスワップを含めることができます。実装方法によっては、実際にスローすることもできますが、スローするデストラクタを使用しないようにする必要があります。例外の場合、swapスローしないことを保証するスワップ操作を提供することが、クラスで強力な例外保証を実現する最も簡単な方法です。 、コピーして脇に置くことができるので、コピーで操作を実行してから、オリジナルと交換します。

ただし、この言語ではデストラクタとスローの両方が許可されていることに注意してください。最も単純なケースでは、オーバーロードしないとスローできます。次に、コピー構築、代入、および破棄、それぞれが例外をスローできる 3 つの操作を実行します (型によって異なります)。swapswap std::swap

デストラクタのルールは C++11 で変更されました。つまり、例外仕様のないデストラクタには暗黙のnoexcept仕様があり、これは、例外がスローされた場合にランタイムが を呼び出すことを意味しterminateますが、例外仕様をnoexcept(false)次に変更できます。デストラクタもスローできます。

結局のところ、C++ のほとんどすべての関数でスローが許可されているため、コード ベースを理解していなければ、例外の保証を提供することはできません。

于 2012-07-23T04:03:03.483 に答える
9

したがって、これはあなたの質問に完全に答えるものではありません-私は自分の好奇心から少し検索しました-しかしスロー保証関数/演算子は、ほとんどがC++で利用可能なCスタイルの関数といくつかの関数に由来すると思いますそのような保証を与えるのに十分簡単です。一般に、C++ プログラムがこの保証を提供することは期待されていません (いつ std::nothrow を使用する必要がありますか?)そして、そのような保証が、例外を定期的に使用するコードで何か有用なものを購入するかどうかは明らかではありません. スワップ、デストラクタ、およびプリミティブ操作のリスト以外に、非スロー関数であるすべての C++ 関数の包括的なリストを見つけることができませんでした (これを指示する標準を見逃していた場合は訂正してください)。また、ライブラリで完全に定義されていない関数に対して、ユーザーが nothrows 関数を実装する必要があることはかなりまれです。

したがって、おそらくあなたの質問の根幹にたどり着くには、C ++で何でもスローできると想定し、絶対に例外をスローできないものを見つけたときにそれを単純化する必要があります。例外セーフ コードを作成することは、バグのないコードを作成することによく似ています。思ったより難しく、正直なところ、多くの場合、努力する価値はありません。さらに、例外の安全でないコードと強力な非スロー関数の間には多くのレベルがあります。これらの点の検証として、例外セーフ コードの記述に関するこの素晴らしい回答を参照してください: Do you (really) write exception safe code? . ブースト サイトhttp://www.boost.org/community/exception_safety.htmlには、例外の安全性に関する詳細情報があります。

コード開発に関して、教授やコーディングの専門家から、例外をスローすべきものとスローすべきでないもの、およびそのようなコードが提供する保証について、さまざまな意見を聞いてきました。しかし、かなり一貫した主張として、簡単に例外をスローできるコードは、そのように非常に明確に文書化するか、関数定義でスローされた機能を示す必要があります (C++ だけに常に適用できるとは限りません)。例外をスローする可能性のある関数は、決してスローしない関数よりもはるかに一般的であり、発生する可能性のある例外を知ることは非常に重要です。しかし、ある入力を別の入力で除算する関数が 0 除算の例外を決してスローしないことを保証することは、まったく不要/望ましくない可能性があります。したがって、nothrow は安心感を与える可能性がありますが、安全なコード実行に必要ではないか、常に役立つわけではありません。

元の質問に対するコメントへの回答:

例外をスローするコンストラクターは、コンテナーまたは一般にスローする場合は悪であり、2 段階の初期化と is_valid チェックを常に使用する必要があると述べる人が時々います。ただし、コンストラクターが失敗した場合、多くの場合、修正できないか、または独特の悪い状態になります。それ以外の場合は、コンストラクターが最初に問題を解決していたはずです。オブジェクトが有効かどうかを確認することは、例外をスローする可能性が十分にあることがわかっているオブジェクトの初期化コードの周りに try catch ブロックを配置するのと同じくらい困難です。それで、どれが正しいですか?通常、コード ベースの残りの部分で使用されたもの、または個人的な好みのいずれかです。私は例外ベースのコードを好みます。すべてのオブジェクトの有効性をチェックする大量のバゲージ コードがなくても柔軟に感じられるからです (他の人は同意しないかもしれません)。

これにより、元の質問とコメントにリストされている拡張機能はどこに残りますか? 提供された情報源と、C++ の「例外の安全性」の観点から nothrow 関数を心配する私自身の経験から、コード開発を処理するためのアプローチが間違っていることがよくあります。代わりに、あなたが知っている機能が合理的かもしれないことを覚えておいてください例外をスローし、それらのケースを適切に処理します。これは通常、何が例外をトリガーするかを完全に制御できない IO 操作に関係しています。予期していなかった、またはあり得ないと考えていた例外が発生した場合は、ロジック (または関数の使用に関する仮定) にバグがあり、ソース コードを修正して適応させる必要があります。自明ではないコードについて保証しようとすることは (時にはそうである場合もあります)、サーバーがクラッシュすることはないと言っているようなものです。

于 2012-07-23T04:40:56.290 に答える
6

この質問に対する詳細な回答が必要な場合は、http://exceptionsafecode.com/にアクセスして、C++03 のみをカバーする 85 分間のビデオ、または両方をカバーする 3 時間 (2 部構成) のビデオをご覧ください。 C++03 および C++11。

Exception-Safe コードを作成する場合、異なることがわかっていない限り、すべての関数がスローされると想定します。

要するに、

*) 基本型 (の配列とポインターを含む) は、ユーザー定義の演算子を含まない演算 (例えば、基本整数と浮動小数点値のみを使用する数学) との間で割り当ておよび使用できます。ゼロによる除算 (または結果が数学的に定義されていない式) は未定義の動作であり、実装に応じてスローされる場合とスローされない場合があることに注意してください。

*) デストラクタ: 例外を発行するデストラクタに概念的に問題はなく、標準で禁止されているわけでもありません。ただし、適切なコーディング ガイドラインでは、言語がこのシナリオを十分にサポートしていないため、通常は禁止されています。(たとえば、STL コンテナ内のオブジェクトのデストラクタがスローした場合、動作は未定義です。)

*) swap() を使用することは、強力な例外保証を提供するための重要な手法ですが、swap() がスローされない場合に限ります。一般に、swap() が非スローであると想定することはできませんが、このビデオでは、C++03 と C++11 の両方でユーザー定義型の非スロー スワップを作成する方法について説明しています。

*) C++11 では移動セマンティクスと移動操作が導入されています。C++11 では、swap() は移動セマンティクスを使用して実装され、移動操作の状況は swap() の状況と似ています。移動操作がスローされないと仮定することはできませんが、通常、作成するユーザー定義型に対して非スロー移動操作を作成できます (標準ライブラリ型に対して提供されます)。C++11 でスローしない移動操作を提供する場合、スローしない swap() を無料で取得できますが、パフォーマンス上の目的で独自の swap() を実装することを選択する場合があります。繰り返しますが、これはビデオで詳しく説明されています。

*) C++11 では、noexcept 演算子と関数デコレーターが導入されています。(Classic C++ の "throw ()" 仕様は非推奨になりました。) また、スローしない操作が存在するかどうかに応じて状況を異なる方法で処理するコードを記述できるように、関数のイントロスペクションも提供します。

ビデオに加えて、exceptionsafecode.com Web サイトには、C++11 用に更新する必要がある例外に関する書籍や記事の参考文献があります。

于 2012-07-30T00:33:38.277 に答える