2017-12-14 10 views
-2

throwを使って何かを返す関数を見ました。スローとリターンをいつ使う必要がありますか?

これを聞く前に、ここで約throwの研究をしましたが、あまり見つけられませんでした。

throwを返信して何かを返信し、通常のreturnの声明を使用するときに誰かが私に説明することができたら、それはすばらしいことになります。

+1

FYI:C++プラスWindowsフォームはおそらくC++/CLIであり、C++ではありません。 – crashmstr

+2

[例外をスローしたときにどうなるのですか?](0120-338-331) – Billa

+2

'throw'を使用して例外をスローします。例外。例外については、[C++の本](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)を参照してください。 OT:C++にはWindowsフォームがありません。あなたはC++/CLI、**ではなく** C++を使用しているかもしれません。 –

答えて

0

returnは、計算された値、クラスメンバーへの参照、状態情報(例:enum値)、簡単な成功/失敗情報、および、および。これは、関数値を評価する最も一般的で一般的な方法です。 (アルフはすでに答えのように)一方

throw

exception年代を扱って - 名前がすでにかなり明確に述べている、:)通常の制御フローの例外:「非常に重要な何か(悪いことが多いものを)起こりました即時処理が必要なので、通常の処理フローを続行できず、すぐに例外をスローする必要があります。 "その理由は、時にはプログラムの壊滅的かつ回復不能な状態になることもありますが、必ずしもそうではありません。例えば、接続を失っているソケットは非常に一般的であり、壊滅的なものではありませんが、ソケットコードが計算を続行できない可能性があるため、例外をスローする理由となります。

通常、例外は通常の戻り値よりも処理しにくく、プログラム設計に統合するのが難しく、既に述べたように単純な戻り値よりも効率が悪いものの、多くの利点があります。

彼らは、関数呼び出しのスタック内のどこからでもキャッチすることができ のは、あなたがゲームエンジン(例えばオーガ)と、ゲームを書きましょう、と。このエンジンは、ダイレクトXインタフェースを使用しています。 DirectXインターフェイスが深く深く入り込んでしまい、エンジンが正常に動作しなくなってしまいます。 正常に機能しないこの関数のエラー処理(呼び出しスタックの深さが8-10である可能性があります)は、通常の戻り値で行われるとほぼ不可能になります。エンジンプログラマとゲームプログラマー。その場合、例外なく、選択する方法は標準化されていないエラーハンドラになります。例外と非常によく似ていますが、例外の強力な可能性はありません。ここでの例外を除いて、このエラーを処理する方法についての実践的な例としては、(機能の真の目的を無視してくださいだ、それだけで原理を示すことです:

​​

我々は、我々がないことを知っている、ここでオクルージョンクエリを行っていますendOcclusionQuery()がすべて正常に機能するときは、catch()は呼び出されず、すべて正常です。 例外がスローされた場合は、例外がスローされます。例外の数とその記述をチェックします。これらの情報が特定の値を持つ場合、それは良質のエラーであることがわかりますので、無視して次のフレームを実行してください。私たちはハンドリングする方法を知らない彼らが選択的に評価することができ

:、次のポイントに私をもたらし呼び出し階層の下位catch()にexceplionの取り扱いを残し、我々だけでthrow;を、それを電子。 上記の例では、タイプOgre::Exceptionの例外をキャッチして処理しますが、それ以外は何も処理しません。 std :: exceptionまたは別の例外タイプは捕捉されません。たとえば、endOcclusionQuery()が独自のコードでコールバックを呼び出し、例外状態になってスローするとします。私たちはこの例外を通過させ、それを処理するためにコール階層の下位(またはそれ以上)のレベルにします。

これらは再投げられます。 この例では、throw;を使用して、呼び出し階層の下位レベルに処理を再スローして渡します。

彼らは を保存しても、別のスレッドで再スローされる可能性は、ワーカースレッドの数百のライブラリ、およびこれらのスレッドを調整マネージャスレッドを想像してみてください。例外は単一のスレッドにバインドされているので、マネージャスレッドはワーカースレッドから例外を捕捉することはできません。しかし、ワーカースレッドは独自の例外をキャッチし、可能であればそれらを処理したり、それらを格納したり、マネージャスレッドに渡したりすることができます。マネージャスレッドは再スローしてマネージャスレッドで処理できます。彼らは、コンストラクタで コンストラクタをスローすることができる

は、戻り値はありません、そして戻り値とその成功を確認することは不可能です。国家のメンバーは可能ですが、扱いにくい - 見落としがちです。したがって、コンストラクタのエラーを処理するための好ましい方法は、(もちろん、文書化された動作として)スローすることです。それはこれに来るときもThrowing exceptions from constructors

彼らは まあ標準化されて参照してください、上記の例では、最高ではありません。 OgreはC++ 11よりかなり前のかなり古いエンジンなので、例外クラスは独自のものです。 charからclass LiverSausageに何かを投げることができます。しかし、今日はもうこれをすべきではありません。std::exceptionが選択のクラスです。これには、単純な例外に必要なものすべてが含まれており、より洗練された例外のために継承することができます。これは、一般的に使用され、STLに継承され、ヘルパークラスと関数はstd::current_exception()など、std::exception_ptrなどがあるさ

彼らが回復不能なプログラムエラーのための安全な救済策として使用することができます。最後に、残念なことにこのような醜い何かが最高のプログラムで起こる可能性があります。あなたはこの致命的な例外をプログラムのどこにでも投げることができますし、エラーをログに記録したり、どこから来たのかを評価したり、ダンプを書き込んだりすることができるの例外を一箇所で行うことができます。 )単純にクラッシュするのではなく、少なくとも悪化することはありません。

0

throwは例外をスローするために使用されます。つまり、プログラムの特定の条件がランタイムエラーまたは誤動作を引き起こすと思われる場合は、例外をスローして回避します。そのようなランタイムエラーを処理します。戻り値は、関数と値を呼び出し関数に返すために使用されます。

+0

スローされた例外の中に 'return'edしたい面白い情報を置くことができます。通常は良い考えではなく、例外を介して返されますが、それは実行できます。 – user4581301

1

throwを使用すると、結果が深くネストされた再帰で役立つことがあります。各コール・レベルをバックアウトするのではなく、この目標の最上位レベルのコールに戻ることができます。他のほとんどの状況では、(例外処理に最適化された例外があるため)非効率的であり、考慮すべきでもありません。

+2

私はダウンボートしなかったが、もし私があなただったら、私はいくつかの批評を完全に期待するだろう。マントラは「フロー制御の例外を使用しない」というのは今日の法律です。 – SergeyA

+0

これは 'goto'と同じです。まったく非難されましたが、まれにしか管理されていない環境でも非常に有用です。 「なぜこの奇妙なことが行われたのですか?それをどうすれば利用できますか?これは良い答えです。 – user4581301

+0

@ user4581301「goto」は醜い獣で、不吉であるという評判を得ていますが、速いです。例外は、必ずしも軽量であるとは限りません。ポップしている例外の種類とそれをどのように救済しているかによって、オーバーヘッドが大きくなる可能性があります。他に道がないために例外と「goto」のどちらかを選択しなければならないと、残念ながら「goto」が勝つだろう。あなたが*本当に*醜いを得たいなら、['longjmp'](http://en.cppreference.com/w/cpp/utility/program/longjmp)を使うことができます。 – tadman

0

例外を処理するためにスローを使用できます。このコードを見てください:

#include <iostream> 
#include <stdexcept> 

int i = 0; 

int main() { 
    if(i == 0) { 
     throw std::runtime_error("Error, I is equal to 0"); 
    } 
    std::cout << "I is not equal to zero, program finished."; 
} 

エラーは、「i」はゼロに等しいこの例では、発生した場合は、プログラム全体が停止し、このエラーメッセージを取得:あなたが削除した場合

terminate called after throwing an instance of 'std::runtime_error' 
what(): Error, I is equal to 0 

をただし、例外は機能しません、先に進んでそれを試してください。

Returnは、関数を実行した後、その関数が何をしたかを知ることができるように使用されます。このコードを見てください:

#include <iostream> 
#include <stdexcept> 

int i = 0; 

int errorOccured() { 
    return true; 
} 

int main() { 
    bool x = errorOccured(); 

if(x == true) { 
    std::cout << "Major error occured"; 
} 

else if(x == false) { 
    std::cout << "No error occured"; 
    } 
} 

errorOccured()が、この場合にtrueを返した機能を、そしてあなたは、単にエラー処理に限定されるものではないX.「リターン」にその戻り値を格納することができました、あなたはすべて行うことができますリターンで物事の種類。関数に複雑な計算を実行させ、結果を返すことができます。だからそこには、実行時に何が起こっているのかを見るための2つの異なる方法があります。

スローに関する詳細はhereと返信約hereです。また、1人で「キャッチ」を募集しています。これは約hereで読むことができ、興味深い読書ができます。

0

これは悪いかもしれませんが、私は実際にこの決定を導く強力な要因となりました。現代のほとんどのオプティマイザはゼロコスト例外処理と呼ばれるものを実装しています。これは最終的に「ブランチのない通常の実行パスですが、高価な例外的なパス」に変換されます。

throwingは、あなたの通常の実行パスを本当に安くする代わりにかなり高額にします。正確な数値はありませんが、try/catchブロックを使用してデータ構造にキーが存在するかどうかをテストするだけでは、おそらく比較的高額です。

私が有用であると分かったもう一つの指導力は、プログラマの制御の外にある外部例外の考え方です。その例としては、繰り返し試行した後、破損したファイルに遭遇したり、メモリの割り当てに失敗したりするようなサーバに接続できないクライアントがあります。

プログレスバーの中止ボタンをユーザーが妨害しているかどうかについて、同僚と一度は議論しましたが、これは例外的な状況です。操作は通常正常に行われるはずだから、ユーザーが中断することは、開発者のコ​​ントロールの外では本当に例外的な状況だから、本当にそれと思った。さらに、コールスタック全体にアボートステータスを伝播しようとして、コードをかなり単純化しました。

人々が例外的なコントロールフローとは何かについて意見が一致しない場合は、決定要因と同じようにパフォーマンスを使用します。ここでは、高価な操作を中止することを捨てることは、パフォーマンス上の大きなオーバーヘッドではありません。なぜなら、クリティカルループで100万回を投げているようなものではないからです。非常に高価な操作を中止するために1回だけ投げているだけです。投げのオーバーヘッドがかなり簡単になります。それは、パフォーマンスが決定的な要素であることについて私が話したときの意味です。

関連する問題