C ++ 03 throw()指定子C ++ 11 noexceptの違い


100

実行時とコンパイル時にそれぞれチェックされることthrow()noexceptそれ以外に違いはありますか?

このWikipedia C ++ 11の記事は、C ++ 03スロー指定子が非推奨であることを示唆しています。
なぜそうnoexceptなのか、コンパイル時にそれらすべてをカバーするのに十分な能力があるのですか?

[注:この質問この記事を確認しましたが、サポート終了の明確な理由を判断できませんでした。]


7
これにAccodring 素晴らしい記事はまた、noexcept実行時チェックが発生する場合があります。その破壊され、それらの間の主な違いnoexceptの原因をstd::terminate破壊しながら、throw原因をstd::unexpected。また、これらの場合のわずかに異なるスタックの巻き戻し動作。
Fiktik

一部の例外仕様で「コンパイル時」がチェックされ、「ランタイム」が他でチェックされることはありません。これは、C ++例外仕様の反対者によって作成された単なる神話です。
curiousguy

回答:


129

例外指定子は一般的にひどい考えであるため、例外指定子は廃止されました。noexceptこれは、例外指定子の合理的に有用な用途の1つである、関数いつ例外をスローしないかを知るために追加されました。したがって、それはバイナリの選択になります。スローする関数とスローしない関数です。

noexceptより強力throw()だからという理由以外に、単にすべてのスロー指定子を削除するのではなく、追加されましたnoexceptnoexceptコンパイル時にブール値に解決されるパラメーターを持つことができます。ブール値がtrueの場合、noexceptスティックします。ブール値がfalseの場合、noexceptは固定されず、関数がスローする可能性があります。

したがって、次のようなことができます。

struct<typename T>
{
  void CreateOtherClass() { T t{}; }
};

CreateOtherClass投げる例外を?Tデフォルトのコンストラクタで可能な場合は、そうなる可能性があります。どうやってわかりますか?このような:

struct<typename T>
{
  void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};

したがって、CreateOtherClass()指定された型のデフォルトのコンストラクターがスローする場合にのみスローされます。これにより、例外指定子に関する主要な問題の1つが修正されます。それは、コールスタックを上に伝搬できないことです。

でこれを行うことはできませんthrow()


+1とにかく私にとって有用な答え。それでも、なぜ私が使いたいのかという答えを探していますnoexcept。私はthrow()これまでに指定子を使用したことがなく、noexcept実際にメリットがあるかどうかを確認しようとしています(コンパイラチェックドキュメント以外)。
hmjd 2013

ちょうどこのstackoverflow.com/questions/10787766/…を見つけた…...
hmjd

1
@NicolBolasは同意します。ただし、noexceptが保証される場合、コンパイラは、関数がデストラクタでスローするかどうかをチェックできます。したがって、関数に例外がないかどうかをプログラマーに警告することができます。
アレックス

2
@NicolBolasランタイムが呼び出しますstd::terminate。これはWAYより悪いです!コードは、機能がマークされたリリースに潜入しnoexcept 、実行時に(つまり、お客様のサイトで)違反が検出されます。そもそもコンパイラが例外をスローしないコードを生成することを保証することを意味しました。
アレックス

2
@NicolBolas:注目に値するもう1つの違い。機能がマークされている場合throws()、例外がスローされている場合、スタックは、必要があり、その時点で(関数内のすべての自動変数が破壊されるように)その機能の範囲件まで解かことterminate()(VIAと呼ばれますunexpected())。関数にマークが付けられているnoexcept場合、例外がスローされると、終了が呼び出されます(スタックの巻き戻しは実装定義の詳細です)。
マーティンヨーク

33

noexcept コンパイル時にチェックされません。

実装は、実行時に含まれている関数で許可されていない例外をスローまたはスローする可能性があるため、式を拒否しません。

宣言されている関数、noexceptまたはthrow()例外をスローしようとするときの唯一の違いは、1つの呼び出しterminateと他の呼び出しunexpected、および後者の例外処理スタイルが事実上非推奨になっていることです。


ただし、仮想関数にthrow()/があるnoexcept場合、コンパイル時のチェックで、オーバーライドが必ずあることを確認します。
curiousguy '10 / 10/28

2

std::unexpected() 動的例外仕様に違反すると、C ++ランタイムによって呼び出されます。例外仕様がこのタイプの例外を禁止している関数から例外がスローされます。

std::unexpected() プログラムから直接呼び出すこともできます。

どちらの場合も、std::unexpected現在インストールされているを呼び出しますstd::unexpected_handler。デフォルトstd::unexpected_handlerはを呼び出しますstd::terminate

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.