P71
- 構造体のメンバーにアクセスする方法
アロー演算子の場合は、ポインターなので間接参照演算子を使って、a->b
なのであれば (*a).b
と書き換えることもできる。
構造体って C# だと値型だけど、C++ だとそういう感じではないのかな。関数は生やせないみたいなのでそこも違うか。
P72
構造体の初期化。{}
を使って配列のように初期化できる。
struct product { int id; int price; } product a = { 0, // id 100 // price };
P74
共用体。構造体に似ているが、すべてのメンバー変数が同じアドレスを参照している。
使い道はわからん。
P78
列挙体。
P81
クラス概要。
- 構造体との違いは、データに加えてその処理もまとめて扱うこと。
- 構造体と同様に変数を作った上で扱うが、そのことを 実体化やインスタンス化(instantiation) と呼ぶ
- 構文はほとんど構造体と同じ
struct
の代わりにclass
を使う
- 構文はほとんど構造体と同じ
P86
参照。
おいおい、なんでアドレス演算子と同じ &
を使うんだよ。
type-name& reference-name = variable-name
参照とポインターの違い
int value = 42; int* pointer = &value; // アドレス演算子でアドレスを取得し、ポインター変数に格納 int& reference = value; // 参照を格納。内部としてはアドレスを共有しているのだと思う。 // pointer のアドレス pointer // reference のアドレス。アドレスを共有しているが値なのでアドレス演算子が必要。 &reference // pointer の値。ポインター変数なので間接参照演算子で値を取り出す。 *pointer // reference の値。値なのでそのまま。 reference
参照は後から付け替えられない。
int value = 42; int ohter = 0; int& reference = value; reference = other; // other の値が reference の値に入っただけで、reference のアドレスは value のままになる。 // &other != &reference
const参照
参照はそもそもアドレスを変更できないので、参照する値が const になっている。
注意点としては、const な値や const な参照をさらに参照で受ける場合に、受ける側も const をつけなければいけない。
const int constant = 42; // const な値 const int& ref_constant = constant; // const な参照 int& ref1 = constant; // NG const int& ref1 = constant; // OK int& ref2 = refconstant; // NG const int& ref2 = refconstant; // OK
P94
式の型を推論する
decltype(expression)
で使える。typeof
みたいな単に型を調べるだけではなくて、それで宣言にも使える。
TypeScript の ReturnType みたいな感じなんやろか。。この時点では利用例が無いので不明。
P95
配列の型推論
なんか突然 auto array[] {0, 1, 2}
みたいな、これまでに無い配列の初期化の方法がでてきたりでよく分からない。
とりあえず、「型推論を使うことでは配列を宣言できない」ということらしいので忘れる。
P97
型の別名定義
using new-type-name = old-type-name
C# と同じに見える。
関数内でも使えるよう。
ネストした型名
- class の内部でさらに別名定義ができる
- 関数の実装の戻り値など、クラスのスコープ外ではフルネームで書くが、関数の実装の内部であれば、別名を直接呼び出せる。
class data { public: using interger = int; // ここは class の内部なので integer が使える integer get_value(); void set_value(integer new_value); private: integer value; }; // class の外側なので data::integer とフルネームで data::integer data::get_value() { return value; } // 引数は class の内側という扱いらしい void data::set_value(integer new_value) { // ここも内側 integer tmp = new_value; value = tmp; }
C言語との互換性
typedef old-type-name new-type-name
using
と逆の順番。
P101
コンソールからの入力
std::cin
入力受付。宣言済の変数に値を格納。- ただし、指定した変数の型通りにしか受け取れず、
std::string
で受けた場合には空白が無視されたり、空白で切られたりする
- ただし、指定した変数の型通りにしか受け取れず、
std::istream& getline(std::istream& input, std::string& str)
で 1行をすべて受け取れる- 使い方としては
std::getline(std::cin, s)
のような形。std::cin
がistream
らしい。
- 使い方としては
P109
デフォルト引数
C# と同じような感じ。可変長とか名前付き引数もあるんだろうか。
P111
[](parameters...) -> return-type
{
lambda-body
}
ラムダ式は必ず auto
で受ける必要があるらしい。コンパイラーが作ったユニークな型が割り当てられるため。decltype
でもそれを再利用はできない。
戻り値の型の省略
型推論で省略可能。
[](parameters...) { lambda-body }
まさかのアローが消された。
変数のコピーキャプチャ
- ラムダ式の先頭の
[]
がキャプチャ対象の指定になっている。 [variable, variable...]
か[=, variable, variable...]
のいずれか。=
はラムダ式内で使っている変数をコンパイラーが自動でキャプチャする。[=]
でいいらしいが、他に変数を指定する用途はなんだろうか?
変更可能なコピーキャプチャ
- コピーとしてキャプチャしいた変数は暗黙的に
const
となる - キャプチャした変数事態を変更する場合には、
mutable
指定する- ただし、キャプチャした変数すべてが対象となる
[variable, variable...](parameters...) mutable -> return-type { lambda-body }
- 当然ながらコピーなので、変更したとしてもコピー元の変数に影響は無い。
参照を取得するキャプチャ
- 当然コピー以外に参照をキャプチャするケースもある
- この場合は
mutable
不要で変更可能- ただし、キャプチャした変数が元々
const
であれば変更不可
- ただし、キャプチャした変数が元々
[&variable, &variable...](parameters...) mutable -> return-type { lambda-body } [&, &variable, &variable...](parameters...) mutable -> return-type { lambda-body }
先頭に &
を付けるのは、デフォルトのキャプチャ =
の代わりに、デフォルトのキャプチャをすべて参照で行うことを宣言する。