こんにちハルマゲドン
「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 ((ab) = 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++の基礎知識の塊なので,経験を積んでから読み返した時を楽しみにしてます.