[Effective C++] Ch1. C++であれば、C++の方法に従います.


Item 1. C++を言語の連合体と見なす必要がある
初期のC++はC言語の中でいくつかのオブジェクト向けの機能を結合しただけです.
C(C with Closses)、初期名にもクラスを使用
増え続けるC++はマルチプログラミング言語となっている
C++をよりよく理解するために,プログラミング規則の下で集約された統合言語ではなく,4つのサブ言語の連合体として理解した.
  • C
    依然としてデフォルトのC部分
  • オブジェクト向けコンセプトC++
    クラス、カプセル化、継承、多形性、および仮想関数を含むオブジェクト向け部分
  • テンプレートC++
    C++の汎用プログラミング部
  • STL(Standard Template Library)
    コンテナ、反復器、アルゴリズム、および関数オブジェクトを含むテンプレートライブラリ部分
  • Item 2. #defineを書くならconst、enum、inlineを思い出す
    「プリプロセッサよりもコンパイラを近づける」
    1.constの使用
    #define ASPECT_RATIO 1.653
    コンパイラに移動する前に、このコードは前処理者によってASPECT RATIOを数値に置き換えます.
    定数で置き換えられたコードでコンパイルエラーが発生した場合、原因が混同される可能性があります.
    ソリューションはマクロではなく定数を使用します
    const double AspectRatio = 1.653;
    AsspectRatioは言語でサポートされる定数タイプであるため、シンボルテーブルに簡単にデバッグできます.
    マクロを使用すると、ASPECT RATIOが表示されると、プリプロセッサはすべて1.653に変更されます.ターゲットコードには1.653個のコピーがあるため、最終的なサイズは大きくなります.
    定数タイプのパーセンテージは複数回書き込まれますが、コピーは1つしかないため、最終サイズは小さくなります.
    2.enumの使用
    クラスのコンパイル中に定数の値が必要な場合は、列挙者遁甲術を使用します.
    Enumは#defineのようにメモリ割り当てを行わない
    class temp
    {
    	const int a = 10; // error
        	enum {a = 10}; // ok
        	int data[a];
    };
    3.インラインの使用
    関数マクロではなくinline template関数を使用すると、従来の関数のすべての操作方法とタイプのセキュリティを実現できます.
    #define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
    上のコードは次の場合、予想外の動作をします.
    int a = 5, b = 0;
    CALL_WITH_MAX(++a, b); // a is incremented twice
    したがって、inline template関数(以下に示す)を使用すると、より安全です.
    template<typename T>
    inline void callWithMax(const T& a, const T& b)
    {
    	f((a > b) ? a : b);
    }
    Item 3. 兆しさえあれば、constをください.
    contを使用して宣言すると、コンパイラが使用上のエラーを特定するのに役立ちます.
    次のコードの定数を変更しようとすると、コンパイラにエラーが発生します.
    char greeting[] = "Hello";
    
    char *p = greeting;			// 비상수 포인터, 비상수 데이터
    const char *p = greeting;		// 비상수 포인터, 상수 데이터 
    char * const p = greeting;		// 상수 포인터, 비상수 데이터
    const char * const p = greeting;	// 상수 포인터, 상수 데이터
    コンパイラでは、ビットレベルの一定性を維持する必要がありますが、プログラマは概念(論理)の一定性を維持し、プログラミングを行う必要があります.
  • ビットレベルの一定性は、任意のメンバー関数がオブジェクトの任意のデータメンバー
  • に触れる必要はない.
  • 論理定数は、定数メンバー関数ではオブジェクトの1つのビットを変更できないのではなく、ユーザーがそれに注意しない限り、定数メンバーシップ
  • があるビットを変更することができます.
    class temp 
    {
    	char& operator[](size_t p) const
        	{
        		return pText[p];
        	}
    private:
    	char *pText;
    };
    
    const temp t("Hello");
    char *pc = &t[0];
    *pc = 'h';
    上記のコードでは、オペレータ[]関数は定数メンバー関数であり、ビットレベルの定数を満たすため、コンパイラでエラーは発生しません.
    ただし、これらのアドレスを使用してデータを変更できるため、プログラマは論理的一定性を維持し、プログラミングを行う必要があります.
    Item 4. オブジェクトを使用する前に、オブジェクトを初期化する必要があります.

  • 組み込みタイプのオブジェクトを直接手で初期化します.
    自分で変わることもあるし、変わることもあるから.

  • 作成者では、メンバー初期化リストを使用しないでください.データ・メンバーの代入文を作成者の本文に配置します.
    基本ジェネレータを呼び出した後にレプリケーションペア演算子を連続的に呼び出すよりも、1回のレプリケーションジェネレータを呼び出す方が効率的です.

  • 異なるソースコードで定義された静的オブジェクト間の相対的な初期化順序は不確定であることを覚えておいてください.