おもちゃバコ

主に趣味について

「Effective C++ 第3版 -プログラムとデザインを改良するための55項目-」を読んだ

こんにちハルマゲドン

「Effective C++ 第3版 -プログラムとデザインを改良するための55項目-」を読んだ備忘録です.


Amazon

内容

C++でプログラムを書く時のテクニックをまとめたもの.
非常に濃い.

対象

C++を仕事に使用している人.
C++入門後の参考書を求めている人.
C++を理解したい人.

「入門書」ではないです.


要約

イントロダクション

・「プログラミング言語の基礎を学ぶこと」と「効率的なプログラムを設計・実装すること」は全く別のこと.
・この本はC++のリファレンスではない.
 プログラムやデザインを改良するアドバイスをまとめたもの.
・CとC++のどちらのものが使用されるかはインクルードヘッダによって決まる.
 C: size_t
 C++: std::size_t
・explicit
 コンストラクタの暗黙の型変換を使用できなくする.
・未定義動作
 怖い.
・コードの「クライアント」
 コードを使う「コード」や「プログラマ」を意味する.
 クライアントのことを意識しよう.

第1章 C++に慣れよう

C++のサブセット
 C: 大部分はCから来ている.
 オブジェクト指向: C++における「クラス付きC」.
 テンプレート: ジェネリックプログラミング,TMP.
 STL: STL独自のコンベンションに従おう.
プリプロセッサよりコンパイラを使おう.
 #defineは数値に置換される.
  コンパイルエラー時にシンボルが出ない.
  -> const定数に置き換えよう.
 定数の使用.
  クラスで使用する定数はstatic.
  ヘッダで宣言,ソースで定義.
 #defineにはスコープがない.
 enumハック
  宣言時の初期化が拒否られたときに使用.
  古いコンパイラ対策.
 #defineマクロよりインライン関数テンプレート.
・const
 「変更ダメ」の明示化.
 operatorのconst.
  (ab) = c; の禁止.
  if ((a
b) = c) の防止.
 mutableキーワード.
  constメンバ関数内で書き換えたいときに使用.
 「ビットレベルの不変性」
  コンパイラのconstの扱い.
  「論理的不変性」を保証するコードを書こう.
 非constメンバ関数内でconstメンバ関数呼び出し.
  コードの重複を避ける.
・オブジェクトは初期化しろ.
 自動的に保証されない.
 コンストラクタによる初期化.
  コンストラクタ内での初期化は「代入」.
  初期化は「メンバ初期化子リスト」.
   デフォルトコンストラクタに仕事に関係.
  デフォルトコンストラクタ使用時にも明示的に初期化する.
 初期化の順番は超大事.

第2章 コンストラクタ,デストラクタ,コピー代入演算子

C++が自動で書き,自動で実行するもの
 デフォルトコンストラク
 コピーコンストラク
 デストラク
 コピー代入演算子
コンパイラが自動生成することを禁止する.
 望まない自動生成は禁止しよう.
 privateに隠蔽する.
 Uncopyableクラスを作成し,継承する.
・仮想デストラク
 仮想デストラクタを持たない基底クラスのポインタにdeleteは未定義.
 仮想関数は「派生クラスでの実装のカスタマイズ」.
 理由のない仮想デストラクタは良くない.
  クラスが仮想関数を持つときに使用する.
 仮想デストラクタを持たないSTL
・デストラクタから例外を投げない.
 クライアントが問題対処できるデザインにする.
・コンストラクタやデストラクタ内では仮想関数を呼ばない.
 実行されるのは「その時のオブジェクト型」のもの.
 バグになりやすい.
・代入演算子は*this参照を返すようにする.
・operator=実装は自己代入に備える.
・コピー時はオブジェクト全体をコピー.

第3章 リソース管理

・リソース管理にオブジェクトを使う.
 リソース確保したら管理オブジェクトに渡す.
  RAII.
 リソース管理オブジェクトは解放時にデストラクタを使う.
 参照カウント型スマートポインタ: RCSP
・リソース管理クラスのコピー振る舞いはよく考える.
 Mutexの扱い.
  RAIIオブジェクトの扱い.
  リソースへの参照カウント.
  管理リソースをコピー.
  管理リソースの管理者を変更.
・リソース管理クラスはリソースへのアクセスを付ける.
 RAIIオブジェクトは生リソースにアクセスする必要が多々ある.
  管理リソースへのアクセス提供.
 明示的「get()」か非明示的「暗黙の型変換」.
・対応するnewとdeleteは同じものを使用.
 単独オブジェクトと配列オブジェクトは扱いが違う.
 new[ ]を使用したらdeleteも[ ].
・newで生成したオブジェクトのスマポ私は独立ステートメントで行う.
 例外対策.

第4章 デザインと宣言

・インタフェースは正しいときに使いやすく,間違ったときに使いにくく.
 インタフェースに一貫性を持たせ,組み込み型と同じ振る舞いをするようにすると良い.
 誤用対策には,新しく型を定義し,オブジェクトの値を宣言すると良い.
  また,クライアントにリソース管理を任せない.
 デリータの設定.
・クラスのデザインを型デザインとして考える.
 クラスのデザインとは型のデザイン.
 ★クラス設計時にこの項目を見返す.
・値渡しよりconst参照渡し.
 スライス問題.
 STLの反復子,関数オブジェクトに注意.
・オブジェクトを戻すときに参照を戻さないこと.
 存在しないオブジェクトの参照戻しに気を付ける.
・データメンバはprivate宣言.
 protectedはpublicよりカプセル化を進めるものではない.
メンバ関数より,メンバ・friendでない関数を使用する.
・全引数に型変換が必要なら,メンバでない関数を宣言する.
・例外を投げないswap.
 テンプレート特化.
 自作型のswapが非効率な場合,メンバ関数としてswapを作る.

第5章 実装

・変数の定義は可能な限り先延ばしにする.
・キャストは最小限にする.
 const_cast: オブジェクトのconst性を取り除く.
 dynamic_cast: 安全なダウンキャストに使用.
 reinterpret_cast: 実装依存の低レベルキャスト.
 static_cast: 暗黙の型変換.
 新しいスタイルのキャストは目的が限定されている.
  コンパイルエラーになるのでわかりやすい.
 dynamic_castの使用.
  遅い.
  使用時は設計ミスの可能性がある.
・オブジェクトの内部データへのハンドルを戻さない.
 ハンドル: 参照,ポインタ,反復子.
・コードを例外安全にする.
 例外安全.
  リソース漏れがない.
  データ構造が無効状態になることを防ぐ.
 保証.
  関数が例外に対し基本保証.
  関数が例外に対し強い保証.
  関数が例外に対し投げない保証.
・インラインを良く理解する.
・ファイル間のコンパイル依存性を最小限にする.
 参照やポインタで十分ならオブジェクトの使用を避ける.
 クラスの定義でなく,宣言依存なコードを書く.
 宣言と定義でヘッダを分ける.
 implとpimpl.

第6章 継承とオブジェクト指向

・public継承はis-a関係を表すようにする.
 public継承はis-a関係を意味する.
 全ソフトウェアにとって利用的なデザインはない.
 基底クラスに適用可能なものは,派生でも適用可能にする.
・継承した名前を隠蔽しない.
 using宣言の利用.
・インタフェースと実装の継承を区別する.
 protectedにデフォルト動作を作成する.
 public継承においては,派生クラスは基底クラスのインタフェースを全て継承.
 純粋仮想関数は,インタフェースのみの継承を意味.
 仮想関数は,インタフェースとデフォルトの実装の継承を意味.
・仮想関数の代わりになるもの.
 NVI: 非仮想インタフェース.
 仮想関数を置き換える.
  関数ポインタ
  tr1::function
  別クラス階層の仮想関数.
・非仮想関数を派生クラスで再定義しない.
・継承した関数のデフォルト引数を再定義しない.
 デフォルト引数: 静的結合.
 仮想関数: 動的結合.
コンポジションでhas-a, is-implemented-in-terms-of関係を作る.
・private継承は賢く使う.
 private継承はis-implemented-in-terms-of関係を意味する.
 EBOが働くことがある.
  ライブラリ開発者には重要かもしれない.
・多重継承は賢く使う.

第7章 テンプレートとジェネリックプログラミング

・暗黙のインタフェースとコンパイルポリモフィズムを理解する.
・typenameの2つの意味.
 テンプレート内でネストされた依存型名にはtypenameを使用する.
 テンプレートパラメータ宣言には,classとtypenameがある.
・テンプレート化された基底クラス内の名前へのアクセス.
・パラメータに依存しないコードはテンプレート外へ.
・すべての互換型を受け取るためにメンバ関数テンプレートを使用する.
・型変換させたいならメンバでない関数をクラステンプレート内で定義する.
・型情報に関してはtraitsクラスを使用する.
テンプレートメタプログラミングを意識する.

第8章 newとdeleteのカスタマイズ

・new-handlerを理解する.
・どういうときにnewとdeleteの定義を書くか理解する.
・自前new, deleteを用意するときはコンベンションに従う.
・プレースメントnewの定義時はdeleteも定義.

第9章 いろいろな事

コンパイラの注意を払う.
・TR1を含む標準ライブラリに慣れる.
・Boostに慣れる.


感想

const辺りの内容しか理解できませんでした(ここも怪しい).

ただ,この本はC++の基礎知識の塊なので,経験を積んでから読み返した時を楽しみにしてます.