# 17ex. C++ ________________________________________ ## 1. C/C++の基本 C言語の基本事項 1. 変数は0初期化されない 2. int系同士の除算は整数落ち 3. いわゆる古めかしい言語 - 条件判定は0かそれ以外か - switch文はフォールスルー可能 - #defineで定数用意しがち - 関数は利用より手前に宣言が必須 - 文字列の取り扱い時、nul文字の考慮が必須 - 文字列リテラルは、初期化子という扱い 4. newしない固定配列がある - 固定配列はインスタンスではない。スコープに応じた領域に直接連続確保される - {}で0初期化可能 - ジャグ配列可能 5. エントリポイントはint main(void) 6. C言語は、引数なし関数はfoo(void) - C++はfoo()でよい 7. 配列を受け取る関数の仮引数は配列のように書けるが、この時の仮引数は実際にはポインタである - 「配列は代入される変数にできないが、ポインタは代入される変数にできる」にも関連 8. char[]と*char - char[]は、変数自体の変更はできない。各要素は変更を[i]を通してできる - *charは、変数自体は変更できる。各要素の変更を[i]を通して出来るかどうかは、実際に指しているものが何かによる 9. constは左隣のキーワードを固定する。一番左に記載した場合は右隣のキーワードを固定する 10. newやmallocしない限り、変数スコープが終わると破棄される 11. staticローカル変数が可能 12. ポインタにしない限り、全ては値型 13. 戻り値以外で結果を受け取りたいなら、参照となる「アドレス渡し」or「ポインタの利用」 - ポインタや配列ではないものを参照渡ししたい時に使うのが「アドレス演算子」 - ポインタや配列は、そのまま渡せばよい 14. 先に演算子があり、それに合わせて変数宣言の文法を揃えたため、*pが参照外し - int *p は「*pするとintが返るよ」「*pするとintの変数だよ」というニュアンスの考え方 15. 配列は代入される変数にできないが、ポインタは代入される変数にできる 16. p-> は (*p).のエイリアス 17. typedef struct {...} Foo; 18. include ""は同じ階層を最初に調べる。山括弧はコンパイラに従って探索する 19. 整数型サイズがコンパイラ環境依存 20. 全角文字列を本格的に扱うには基本機能では不足 C++の基本事項 1. C++のstructはCに比べて文法が大幅に拡張されている 2. structとclassの違いは、メンバのデフォルトアクセス修飾子など - 他にも継承後のデフォルトアクセスなど細かい違いはあるもののほとんど差はない 3. GCがない。スマートポインタ等のライブラリの利用が推奨 4. コンストラクタ、代入演算子が複雑 - rule of three/five/zero - 初期化系 - T x; - ユーザ宣言デフォルトコンストラクタがあればそれ - T x(); - そもそも変数宣言にならず、関数宣言として解釈される - T x{}; - T x = T(); - 0初期化 & デフォルトコンストラクタ - T x(a,b); - 対応するコンストラクタ - T x = expr; - exprがTならコピーCtorまたはムーブCtorで構築 - C++17以降の場合は、コピーCtorが省略される場合がある(=prvalueな時) - exprがT以外なら変換可能なコンストラクタで構築。ただしexplicitは候補外 - T x{a,b}; - 初期化子コンストラクタ、なければ対応するコンストラクタ、なければ集成体初期化 - T x = {a,b}; - 初期化子コンストラクタ、なければ対応するコンストラクタ。なければ集成体初期化。ただしexplicitは候補外 - x = y; コピー代入演算子 - コピーCtor:ユーザ宣言のムーブCtor、ムーブ代入がなければ自動生成 - 代入演算 : ユーザ宣言のムーブCtor、ムーブ代入がなければ自動生成 - ムーブCtor : ユーザ宣言のコピーCtor、代入演算、デストラクタがなければ自動生成 - ムーブ代入 : ユーザ宣言のコピーCtor、代入演算、デストラクタがなければ自動生成 - デストラクタ : 無ければ自動生成 - デフォルトCtor : いずれのコンストラクタも宣言されていなければ自動生成 - C++11以降は、= defaultが利用可能 - 言葉で表現すると以下 - 初期化時に右辺を記載しなかった場合、デフォルトコンストラクタで初期化される(trivial除く) - 初期化時にコンストラクタを呼び出した場合、そのコンストラクタで初期化される - 初期化時に別のオブジェクトで初期化される場合、コピーCtor/ムーブCtor/そのまま代入のいずれかが行われる 基本事項から導かれる推奨事項 - ファクトリ関数を用意したい場合 - Cスタイルの場合は、戻り値を使わず引数で参照を渡す - C++でスマートポインタ運用では、スマートポインタを普通に返す ________________________________________ ## 2. C言語互換のC++基本ライブラリ C |所属ファイル |C#の近い機能 ---------|-------------------|----------- size_t |cstddef |ulong printf() |cstdio |Console.WriteLine() scanf() |cstdio |Console.ReadLine() uint8_t |cstdint |byte, bool int32_t |cstdint |int memcpy() |cstring |Array.Copy() strlen() |cstring |byte[]で0x00の位置を探す . C#の近い記述で理解するC言語 ```text // C++ void Foo(int *arg) { *arg = 10; } // C# void Foo(ref int arg) { arg = 10; } // C++ BarClass *pA; pA = pB; // C# BarClass a; a = b; // C++ const int baz[]; // C# (要素が読み取り専用という意味で意味で) IReadOnlyList baz; // C++ QuxClass* const qux = ...; // C# (変数自体の差し替えが出来ないという意味で) readonly QuxClass qux = ...; ``` ________________________________________ ## 3. .vcxprojの運用 - Debugビルドされモジュールはデバッグ用dllを参照する - 同梱しない限り一般環境では動かない - 先にエクスプローラでファイルを追加してから、プロジェクトに追加が良さげ - 無難なフォルダ構成はこれ - src (publicではないもの全て) - include (public予定のヘッダー) - lib (サードパーティ全般) - readme.txt