try, catch, throw による例外処理はメモリーの使用効率が悪いという理由で、C のように関数の復帰値による例外処理をしている(*1)人達がいるのですが、本当に関数の復帰値による例外処理よりもメモリーの使用効率は悪いのでしょうか?
また、悪い場合どれくらい悪いのでしょうか?
*1…例外内容は別途管理しています。
質問の流れにそって、メモリ効率の低下という意味では2つの可能性があると思います。
1.throwされるオブジェクトのメモリ効率
catch節で、値渡し、参照渡し、ポインタ渡しのどれでも自由に受け取ることができます。
ただし、throwされたオブジェクトのコピーが送出されます。その分だけ無駄なメモリを使うといえます。
2.コードサイズに関わるメモリ効率
例外処理を使うと、例外処理にかかる処理の分だけコードサイズが大きくなります。
プログラムサイズが大きくなれば、その分だけメモリ効率は低下するといえるかもしれません。
これらの差というのは、リソース制約が厳しい世界においては大きな問題となるでしょう。
そうでなければ、*パフォーマンス的な意味では*問題にならないと個人的には思います。
だからといって、例外はC++の主たる要素ではありますが、的確に使うことが非常に難しい仕様であることも確かです。
*1の人達がどういった人達か分かりませんが、リソース制約が厳しい世界の開発者であったり、あるいは、その仕様の難しさ故に、チームとして一定の水準のコードを保つためには、例外を使用しない方がよいと考えているのではないでしょうか?
例外については、More Effective C++の例外の章を読むと理解が深まると思います。
何かの参考になれば。
例外処理のオーバヘッドに関する話題は良く聞きますね
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1790955
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja...
少なくとも,例外処理を使うと
が必要になることは事実です.つまり処理時間とメモリ使用量が増加する可能性があります
後者のmsdnの記事でも
このファイルは 23,040 バイトから 29,696 バイトになりました
と例外を使うと,バイナリのサイズが増加する実例が挙げられています.
(この記事が書かれたのは1999年で少々古いデータですが,最近のコンパイラでも例外処理にはオーバヘッドが伴います)
このオーバヘッドが多いとみるか,少ないと見るかは,状況によりますが,
少なくとも,
という点はふまえておいた方が良いと思います.
同上。
先に挙げたMore Effecive C++など、詳しい議論は参照してください。
簡単に、コメントに対して答えると。
> ・throw するオブジェクト
> 関数の復帰値+別途管理する例外内容と同程度だと思います。
これはthrowするオブジェクト次第です。
一概に言えません。JavaのようにThrowableでないとthrowできないとかそういったことはないので、
関数の返り値であれば、定数を返すことも多いでしょうし、それに対応して、整数をthrowすることもできます。
そういった意味で大きな差はここについては無いかもしれません。
> ・throw 文
> 例外内容を設定する処理+関数の復帰値を返す処理と同程度だと思います。
> → 実はオブジェクトの転送処理での使用効率が悪い?
これに答えるとYesになります。先の答に書いたコピーが発生するためです。
throwされた場合でもローカルに作成されたオブジェクトなどは適切に開放されなければいけません。
それらのオブジェクトを開放するコードをコンパイラが生成しています。
これは、私も十分に詳しい訳ではないですが、最適化なども考えると、もう少し違いはありそうな気がします。
> ・try, catch 文
> 関数の呼び出し毎に処理するより、try, catch 文でまとめて処理する方が使用効率が良いと思います。
> → 実は一つの try, catch 文での使用効率がかなり悪い?
これは何を意図されたか把握しきれていないのですが、
Object o; result = f1(); if (!result) { 例外処理 } result = f2(); if (!result) { 例外処理 }
よりも
try { Object o; f1(); f2(); } catch (例外1) { } catch (例外2) { }
となっていて、コードも分かりやすいので、実行コードもシンプルになっているのではないか?ということでしょうか?
もし、そういう意味であれば、答はNoです。
前者の手続き的なプログラムは最適化こそされ、基本的にそのままの動作を実行するコードが生成されます。
それに対し、後者のtry-catchの方は例外処理がうまく実行するようにコードが色々変わります。
例えばですが、f1で例外が発生した場合は、oを解体してcatchブロックのアドレスXXXにジャンプするということを覚えておくような処理などです。
そのため、コード上はシンプルですが、内部的にはもう少しややこしくなるはずです。
上記のように、それらの視点で比較すれば、メモリ効率の差はあることはあります。
また、その効率の低下を可能な限り押さえる方法もあることにはあります。
「質問がメモリ効率が悪い」という視点からのものでしたので、あまり触れませんでしたが、例外処理の仕組みはコードを見て分かる動作よりもずっと複雑です。そのため、それを適切に利用することはC++が使えますという開発者のうちほんの一部の人だと思っています。
それ以外の人が例外処理を利用すると、C++が大人の言語と呼ばれる側面が顔を出してきます。
throw するオブジェクトと例外処理を行う try, catch, throw 文がメモリーを使用するのは当然ですが、それが C のような例外処理と比べて効率が悪いのかという質問です。
私は以下のように思っているのですが、間違っているでしょうか?
・throw するオブジェクト
関数の復帰値+別途管理する例外内容と同程度だと思います。
・throw 文
例外内容を設定する処理+関数の復帰値を返す処理と同程度だと思います。
→ 実はオブジェクトの転送処理での使用効率が悪い?
・try, catch 文
関数の呼び出し毎に処理するより、try, catch 文でまとめて処理する方が使用効率が良いと思います。
→ 実は一つの try, catch 文での使用効率がかなり悪い?