##『More Effective C+』-異常

5043 ワード

More Effective C++
#@author:       gr
#@date:         2015-05-24
#@email:        [email protected]

九、destructorsを利用して資源の漏洩を避ける
RAIIとは「リソース取得は初期化時」であるため,リソースを解放しなければならない.リソースを1つのオブジェクトに格納し、オブジェクトの構造関数に依存してリソースを解放します.
リソースをオブジェクトにカプセル化することで、異常が発生した場合、オブジェクトのプロファイル時にプロファイル関数を呼び出し、リソースを解放し、リソースの漏洩を回避できます.
異常がリソース取得中に投げ出された場合は、10番目の項目を表示します.異常が解析中に発生した場合は、第11条を参照してください.
十、constructors内で資源の漏洩を阻止するconstructorで関数に異常が発生した場合、オブジェクトの構造が完了していないため、その構造関数は呼び出されません.だから私たちは構造関数を期待して整理しています.
BookEntry::BookEntry(const string& name, address, const string& imageFileName, const string& audioClipFileName)
	:theName(name), theAddress(address), theImage(0), theAudioClip(0)
{
	theImage = new Image(imageFileName);
	theAudioClip = new AudioClip(audioClipFileName);	//  AudioClip        ,      Image       
}

「pointer class members」の代わりにスマートポインタを使用すると、リソースをローカルオブジェクトで管理し、異常が発生した場合、BookEntryが自動的に破棄された場合も、指定したオブジェクトを手動で削除しないでください.
十一異常(exception)流出禁止destructors
呼び出しdestructorには、次の2つのケースがあります.
  • オブジェクトは通常の状態で破棄する
  • .
  • オブジェクトはexception処理機構によって
  • 破棄される.
    異常時の状況を議論し,外部のcatchブロックで構造関数を呼び出し,構造関数が間違っている場合にstd::terminate()を呼び出してプログラムを終了させる.このような状況を避けるには、catchブロックにtry-catchを追加することができますが、これは極端に見えます.方法は,異常を生じる可能性のある構造関数において異常のキャプチャを行い,何もしないことである.
    Session::~Session()
    {
    	try{
    		logDestruction(this);
    	}catch(...){}
    }

    十二、「exceptionを投げ出す」と「パラメータを渡す」または「虚関数を呼び出す」の違いを理解する
  • catch句のパラメータタイプpass by referenceメソッドを使用すると、異常な修正に役立ち、効率を向上させることができ、一般的にcatchのパラメータタイプを参照タイプとして定義します.
  • 一致するcatch句a.タイプ変換は関数パラメータマッチングよりも少ないが、算術タイプ変換とクラスタイプ変換はサポートされず、以下のようにのみサポートされる.
  • 非常量から定数への転換
  • 派生クラスからベースクラスへの転換
  • 配列は、配列タイプを指すポインタ
  • に変換される.
    b.マッチング順序関数マッチングはbest-fitで行われ、マッチングパラメータの選択が最良であり、異常問題はfirst fitで行われ、順序に従って行われるので、サブクラス(および特殊タイプ)を汎用タイプの前に置く.
  • 異常放出異常放出:
    Exception ex;
    throw ex;
    異常放出時、catchがどのようにby referenceby valueを捕獲しても複製する必要があり、catch句にあるのはこの異常のコピーである.異常再放出:
    catch (exception& ex)
    {
    	//....
    	throw;					//     exception,      
    }	
    catch (exception& ex)
    {
    	//....
    	throw ex;				//      exception     
    }
  • 十三、by reference方式でexceptionsを捕捉する
    関数伝達パラメータと同様に,効率と正確性のためには参照伝達を行ったほうがよい.
    Catch exceptions by reference !
    十四、賢明な運用exception specificationsexception specificationsとは、関数の後ろに投げ出す異常タイプを加えることです.次のようになります.
    void f2() throw(int);		//     int     
    void f3() throw();			//         

    しかし、exception specificationsは、exception specificationに列挙されていないexceptionを投げ出すと、このエラーが実行時に検出され、特殊関数unexpetedが自動的に呼び出され、プログラムが終了するという問題をもたらす.
    void f1();		//f1     exception specification
    void f2() throw(int)
    {
    	//....
    	f1();		//  f1(),        
    	//....
    }

    解決策は、呼び出された関数がexception specificationsでなければ、呼び出された関数もexception specificationsを加えないことである.
    また、関数ポインタで関数を呼び出すと、登録されたコールバック関数を実装する場合など、この検証も行われます.
    2つ目の問題は、exception specificationsを「タイプ引数が必要」templateに置かないことです.templateは必ず何らかの方法でそのタイプのパラメータを使用するので、templateexception specificationsを混合して使用するべきではありません.
    3つ目の問題は、「システム」が投げ出す可能性のあるexceptionsを処理することである.new operatorを使用すると、bad_alloc異常が放出される可能性があります.
    しかし、いくつかの関数がexception specificationsと書かれている場合は、他のライブラリにexception specificationsがない関数を呼び出すには、これらの関数から投げ出された他の異常をUnexceptedException異常に変換するしかありません.
    class UnexceptedException{};
    void convertUnexcepted()
    {
    	throw UnexceptedException();
    }
    set_unexpected(convertUnexpected);

    しかし、exception specificationUnexceptedExceptionを加える必要があります.そうしないと、terminateは呼び出されます.
    もう1つの方法は、exceptionsを標準タイプbad_exceptionに変換することであり、その実装は、予期しない関数の代替者が現在の(current)exceptionを再び投げ出すと、標準タイプbad_exceptionに置き換えられることに依存する.exception specificationsbad_exceptionを加えるといいです.
    void convertUnexcepted(){
    	throw;			//      exception
    }
    set_unexpected(convertUnexpected);
    exception specificationsは両面刃で、「関数がどのようなexceptionを投げたいのか」という面で優れた説明をしているが、同時に「exception specifications違反」の時も結末は悲惨だ.
    十五、異常処理(exception handling)のコストを理解するexceptionをサポートするためには、プログラムは大量の簿記作業をしなければならない.「天下に無料の昼食はない」という理屈だ.各try文ブロックの進入点と離脱点に記号を付けなければならない.try文ごとに、対応するcatch句が処理できるexceptions型を記録しなければならない.try文ブロックコードを用いて約5%~10%膨張し,実行速度も低下する.パフォーマンス上の問題がある場合は、分析ツール(profiler)を使用してプログラムのパフォーマンスのボトルネックを分析します.