非スロー機能について2つの質問があります。
なぜ関数を非スローにするのですか?
関数を非スローにする方法は?関数内のコードが実際に発生する可能性がある場合
throw
でも、スローしないようにする必要がありますか?
次に例を示します。
void swap(Type t1, Type t2) throw()
{
//swap
}
のコードswap
がまったくスローされない場合でも、追加する必要がありますthrow()
か?なんで?
非スロー機能について2つの質問があります。
なぜ関数を非スローにするのですか?
関数を非スローにする方法は?関数内のコードが実際に発生する可能性がある場合throw
でも、スローしないようにする必要がありますか?
次に例を示します。
void swap(Type t1, Type t2) throw()
{
//swap
}
のコードswap
がまったくスローされない場合でも、追加する必要がありますthrow()
か?なんで?
throw()
(またはnoexcept
C ++ 11では)次の2つの理由で役立ちます。
非スロー関数は、例外安全コードを作成するために非常に重要です。たとえば、例外セーフを作成する通常の方法はoperator=
、非スローswap()
関数を使用することです。
一方、他の例外仕様は役に立たず、現在の標準では正当に非推奨になっています。それらはテンプレートとまったく混ざり合わず、強制するにはコストがかかりすぎます。
これで、実際にスローする可能性のある関数で仕様を使用するとnoexcept
、すべての賭けが無効になります。例外が関数を離れるときにコンパイラーがプログラムを終了しない場合でも(たとえば、実行時の効率上の理由でVSは終了しません)、最適化のためにコードが思ったとおりに実行されない場合があります。例えば:
void f() noexcept
{
a();
b();
}
a()
実際にスローされb()
て副作用がある場合、例外はスローされないことを指定しているため、コンパイラが前に実行することを決定する可能性があるため、関数の動作は予測できませんb()
。a()
編集:あなたの質問の2番目の部分:関数を非スローにする方法は?
まず、関数が本当にスローされないようにする必要があるかどうかを自問する必要があります。例えば:
class C
{
C* CreateInstance()
{
return new C();
}
}
演算子new
はを投げることができるのでstd::bad_alloc
、投げるCreateInstance()
ことができます。try-catchブロックを使用してそれを回避し、try
ブロック内でスローされる可能性のある例外を処理または飲み込むことができますが、それは本当に賢明ですか?例えば:
C* CreateInstance()
{
try
{
return new C();
}
catch (...)
{
return null;
}
}
CreateInstance()
問題は解決したようですが、発信者は戻る準備ができていますnull
か?そうでない場合、そのポインタを使用しようとするとクラッシュが発生します。その上、std::bad_alloc
通常はあなたがメモリを使い果たして、あなたがただ問題を延期するであろうことを意味します。
So be careful: some functions can be made non-throwing, but others should be allowed to throw. Exception safety is not a trivial matter.
なぜ関数を非スローにするのですか?
したがって、関数の呼び出し元は、関数によって発生した例外を処理するためのアクションを実行することなく、関数を呼び出すことができます。
関数を非スローにする方法は?関数内のコードが実際にスローされる可能性がある場合でも、スローしないようにする必要がありますか?
tryブロック内にスローする可能性のあるすべてのコードを配置することでコードを非スローにし、再スローせずに例外を処理できます。
void swap(T t1, T t2) noexcept {
try {
// ....
} catch (const std::exception& ex) {
// ....
} catch (...) {
// ....
}
}
関数がスローされないと主張する場合は、関数をスローしないようにする必要があります。ただし、これは例外仕様を追加することを意味するものではありません。これは非推奨であるため、とにかく行うべきではありません。これは、関数が何があってもスローされないようにする必要があることを意味します。C ++ 11キーワードnoexcept
は、この点でコンパイル時の安全性を提供します。