Exceptional C++Style読書ノート(一)

6829 ワード

第1条vectorの使用
設計vectorは内蔵配列の代わりに使用されるため、内蔵配列と同様に効率的であるべきであり、内蔵配列は下付きインデックス(operator[])では境界チェックを行わない.下限チェックが必要な場合はatメソッドを使用します.
ガイドラインはsize/resizeとcapacity/reserveの違いを覚えています.
  • sizeは、コンテナに現在実際にどのくらいの要素があるかを示しますが、resizeはコンテナの末尾にいくつかの要素を追加または削除します.この2つの関数はlist、vector、dequeに適用されますが、他のコンテナには適用されません.
  • capacityでは、少なくともどれだけの要素を追加すればコンテナにメモリを再割り当てできるかを示します.reserveは、必要に応じてコンテナの内部バッファをより大きな容量に拡張し、少なくとも指定した空間サイズを満たすことができます.この2つの関数はvectorにのみ適用されます.

  •  
     
    ガイドライン
  • constの使用を忘れないでください.iterator.
  • なるべく使う!=<2つのiteratorを比較するのではなく.
  • デフォルトで接頭辞形式を使用する--と++の習慣を身につけます.元の値を使用する必要がない限り.
  • 標準ライブラリの既存のアルゴリズム、例えばfor_each().

  •  
     
    2番目の文字列3番目の文字列のフォーマット
     
         sprintf     snprintf     stringstream     strstream     boost::lexical_cast    
    使いやすいですか.コードははっきりしていますか.効率的ですか.余分なメモリの割り当てはありませんか.長さは安全ですか.タイプは安全ですか.テンプレートに使えますか.
    Yes No No Yes Yes Yes No No No NoYes Yes Yes No No Yes Yes Noいいえはいはいはいはい
     
    ガイドライン
  • 値を文字列に変換するだけで行う場合は、boost::lexical_をできるだけデフォルトで使用します.cast.
  • 簡単なフォーマットを行う場合、または広い文字列をサポートする必要がある場合、またはテンプレートでフォーマットを行う場合は、stringstreamまたはstrstrstreamをできるだけ使用します.
  • 複雑なフォーマットを行いたい場合は、停止に幅の広い文字列をサポートする必要はなく、コードをテンプレートに使用したくない場合は、できるだけsnprintfを使用します.
  • sprintfは決して使用しないでください.

  •  
    第四条標準ライブラリメンバー関数
    標準ライブラリのmem_を使用funは、メンバー関数をシミュレーション関数(functor)に適合させ、標準ライブラリアルゴリズムおよび他の通常のフリー関数のみを適用するコードで使用することができる.しかし、標準ライブラリ自体には使用しないでください.
     
    第五条第六条汎用性のある風味
    ガイドラインオブジェクトの値を交換する方法がある場合は、std::swap()を特化することを考慮してください.
     
    //   :  swap()。
     
    class X {
    public:
        void swap(X&);
    };
     
    //   :         std      。       Koenig  。
    swap(X&a, X&b) {
        a.swap(b);
    }

     
    第七条汎用性のある風味
    ガイドラインでは、関数テンプレートを特化することはできません.再ロードするしかありません.関数テンプレートが特化しているように見える関数テンプレートを書くのは、実際には個別の主関数テンプレートを書くことです.
     
     
    次のコードでは、最後の行のコードがf()のバージョンを呼び出しますか?
    //   :    。
     
    template <typename T>    // (a):     
    void f(T);
     
    template <typename T>    // (b):     ,   (a)
    void f(T*);
     
    template <>              // (c):(a)       (   )
    void f<int*>(int*);
     
    template <>              // (d):(b)       (   )
    void f<int>(int*);
     
    // ....
     
    int * p;
    f(p);                    //        ?

    答えは......呼び出し(d)で、結果は予想外だったに違いない.もし私たちが(d)、f()呼び出しを注釈したら、どのバージョンですか.答えは......呼び出し(b)で、びっくりしたのではないでしょうか.もしこれがあなたを驚かせたら、あなたは唯一ではありません.その時、多くの専門家を驚かせたことがあります.この例を理解する鍵は、テンプレートの特化がリロードに参加しないことです.
     
    準則は、関数テンプレートの特化がリロード決定に関与していないことを覚えています.プライマリ・テンプレートがリロードされた決議で選択されている場合にのみ、その特化バージョンが使用されます.また、コンパイラは、プライマリテンプレートを選択するときに、特化されたバージョンがあるかどうかは気にしません.
     
    関数テンプレートのリロードルールを見てみましょう.
  • 非テンプレート関数はC++の一等公民である.通常の非テンプレート関数が、リロード解析のパラメータマッチングで1つの関数テンプレートと同じように表現されている場合、コンパイラは通常の関数を選択します.
  • コンパイラが適切な一等公民を発見しなければ,主関数テンプレートはC++の二等公民として考慮される.どの主関数テンプレートを選択するかは、どのパラメータタイプが最もよく一致するかによって異なります.
  • この選択された主関数テンプレートがたまたま使用されているテンプレートに対して実パラメータを特化している場合、この特化バージョンはコンパイラによって選択されます.そうでない場合、コンパイラは正しいタイプでインスタンス化されたプライマリテンプレートを使用します.
  •  
     
    ガイドラインは、プライマリ・テンプレートを特化し、リロード決定に参加したい場合(または、ユーザー・コールに完全に一致する場合にコンパイラによって選択されることを確認したい場合)は、通常の関数に書くだけです.
    推論:関数テンプレートのリロードを確実に提供している場合は、特化を避ける必要があります.
     
     
    ガイドライン特化される必要がある可能性のある主関数テンプレートを書いている場合は、できるだけ孤立した、特化されたりリロードされたりしてはいけない関数テンプレートに書き、静的関数を含むクラステンプレートに具体的な実装をすべて入れてください.これにより、プライマリ関数テンプレートのリロード決定に影響を与えることなく、後者を誰でも特化(フル特化またはバイアス)することができます.
     
    //   :    。
     
    template <typename T>
    struct X;
     
    template <typename T>            //         
    void f(T t) { X<T>::far(t); }
     
    template <typename T>            //            
    struct X {
        static void f(T t);
    };

     
    第八条友元テンプレート
    準則はあなたの意図を明確に表現します.テンプレートを指している場合は、テンプレート名の後にテンプレートの実パラメータリスト(空、すなわち<>)を付けることができます.
     
    //   :    。
     
    namespace boost {
        template <typename T> void checked_delete(T* x);
    }
     
    class Test {
        friend void boost::checked_delete<Test>(Test* x);    //  "checked_delete<>(Test* x)"
    }

     
    第9条第10条エクスポート制限
    ガイドラインでは、exportは通常の関数のような本格的な分離コンパイルをもたらすことはできません.
    ガイドラインでは、exportは依存性を隠すだけで、依存性を解消することはできません.
    ガイドライン(現在の場合)exportの使用は避けます.
     
    第十一条第十二条異常安全問題
    ガイドライン
  • は、アプリケーションまたはサブシステム全体のエラーレポート/処理ポリシーを確立し、常にそれに従う.エラーレポート、エラー伝播、エラー処理のポリシーを設定します.
  • は、エラーを検出し、自身が処理できない場所で異常を放出する.
  • は、try/catch(例えば、サブシステム境界上または他のランタイムファイアウォール境界上でcatch(...)を記述するのに十分な知識とコンテキスト情報を備えている.

  • ガイドライン関数は、常にサポートできる最も強力な異常なセキュリティ保証をサポートする必要がありますが、保証を必要としない呼び出し者に追加のオーバーヘッドをもたらすことはできません.
    ガイドラインは、構造関数、リリース操作、およびswap()関数が異常を放出することを決して許さないでください.そうしないと、安全で信頼性の高いリソースクリーンアップはできません.
    ガイドライン
  • は、関数に例外仕様を付けないでください.
  • は、空の例外仕様リスト(すなわちthrow()を宣言したい場合を除き、推奨されません.