はじめてのC++【9日目】

#はじめに
今日はenum class, constexpr, 動的配列とロベールのC++をやろうと思います。
##enum class
###enum classとは
enum classで定義した列挙型は、従来のenumに加えて、**「整数型への暗黙の型変換を行わない」****「列挙型のスコープを持つ」**という機能を持つ。

###enum classができた理由
・型の安全性
・予期しないエラー(スコープがないことによる名前衝突、上記の型安全性の問題による予期しない型変換)
・コードのわかりやすさ(明確さ)
・コードの移植性

（参照）https://cpprefjp.github.io/lang/cpp11/scoped_enum.html

###使ってみる
05-06でenumを使って書いたコードをenum classを使って書いてみる

```enumclass.cpp
#include <iostream>

enum class CompareResult {
    CR_LESS_THAN,//指定しなければ0
    CR_EQUAL_TO,//初期化しなければ前の値+1
    CR_GREATER_THAN,
};

CompareResult Compare(int a, int b)
{
  if(a < b)
  {
    return CompareResult::CR_LESS_THAN;// 単にCR_LESS_THANと指定するのではなく、どの列挙型に属するのかを指定する
  }else if(a > b)
  {
    return CompareResult::CR_GREATER_THAN;
  }else{
    return CompareResult::CR_EQUAL_TO;
  }
}

bool Compare()
{
  int a;
  int b;

  std::cout << "数字を　２ つにゅうりょくしてください > " <<std::flush;
  std::cin >> a >> b;

  if(a == -1)
  {
    return false;
  }

  switch(Compare(a, b))
  {
    case CompareResult::CR_LESS_THAN:
    std::cout<<"前者より後者のほうが小さい" << std::endl;
    break;

    case CompareResult::CR_EQUAL_TO:
    std::cout<<"両者おなじ" << std::endl;
    break;

    case CompareResult::CR_GREATER_THAN:
    std::cout<<"前者は後者よりおおきい" << std::endl;
    break;
  }
  return true;
}

int main()
{
  while(Compare())
  {}
  int a = static_cast<int>(CompareResult::CR_EQUAL_TO);//明示的な型変換はOK
}
```
これからはenum classを使おうと思います。

##constexpr
###constexprとは？
constexpr(constant expression(定数式))というのは、変数ならコンパイル時に値が決まる変数にし、関数ならコンパイル時に実行できる時はする(ここ重要！)ようにできるC++11から追加されたキーワードです。
###constexprをつける目的
算処理を実行時ではなくコンパイル時に移して、実行時のプログラムを高速化することにある。
###どういうときにつけるのか
マクロやconstでの定数はconstexprに変えるべきだ

```例.cpp
const int ARRAY_SIZE = 7;//プログラム実行時ARRAY_SIZEに7が格納される。

constexpr int ARRAY_SIZE = 7;//コンパイラ時にARRAY_SIZEに7が格納される。
```
###関数もできるの？
```cpp
constexpr sqrt(int x){
  return x * x;
} 
```
関数は定数ではないのだができるみたい。
constexpr関数は、関数内で値が変更されてなければ使えるみたい。
###緩和
前はreturn文のみしか使えなかったが緩和された。

・変数宣言を許可
・if文とswitch文を許可
・全てのループ文を許可(for文、範囲for文、while文、do-while文)
・変数の書き換えを許可
・戻り値型(リテラル型)として、voidを許可
・constexpr非静的メンバ関数の、暗黙のconst修飾を削除

変数の書き換えを許可したの！？
>constexpr関数内において、ローカル変数、またはその関数が所属するクラスの非静的メンバ変数の書き換えが許可された。

```cpp
constexpr int square(int x)
{
  x *= x; // OK : ローカル変数は書き換えてもよい
  return x;
}
```
つまり、ローカル変数の書き換えは問題ないということか。

使えるときは使っていこうと思う。
（参照）
https://qiita.com/SAKIchan/items/3df9698d46471cb8aaeb
https://qiita.com/saltheads/items/dd65935878a0901fe9e7
https://cpprefjp.github.io/lang/cpp14/relaxing_constraints_on_constexpr.html

##動的配列
C++では通常の配列を使うのではなく動的配列が基本であるとのこと。
通常配列と同じように [] 演算子で値を参照・代入することはもちろん、サイズ情報等の取得やデータの挿入削除なども可能である。スネークゲームも動的配列を使っているとのこと。面白い！

###インクルード
include ＜vector＞で使えるようになる。名前空間はstd
###生成
std::vector オブジェクトを生成するには「std::vector<型> オブジェクト名;」 と記述する。

```cpp
std::vector<int> a//int型の動的配列 aを生成
``` 
要素数の指定

```cpp
int a[5];//[]を使う
std::vector<int> a(5);//()を使う
```
中身を指定してを初期化する

```cpp
std::vector<int> a{1,2,3};
```
動的配列の機能はたくさんあり、実際に使用する時が来たら確認しに戻ろうと思う。.erase()とか.pushback()とか。

##ロベールのC++
###05-09　静的ローカル変数
静的変数とは、「プログラムが実行される前（プログラムがメモリ上にロードされたとき）に既に位置の決まっている変数」
つまり、グローバル変数は静的変数と言える。
また、ローカル変数にstaticをつけると静的変数になる。

一方、静的変数でない変数のことを「自動変数」「動的変数」という。

以下のことを確認するプログラム
・アドレスは常に一定であるか
・初期化は全体を通して一回しか実行されない。
・明示的に初期化しなければ０で初期化される。
・関数を抜けても値は保証される。

```Static.cpp
#include <iostream>
#include <algorithm>

//アドレスが常に一定かのチェック

void CheckAddress_Sub();
void CheckAddress_Sub2();

void CheckAddress(){
  std::cout << "あドレスが常に一定かのチェック" << std::endl;

  CheckAddress_Sub();
  CheckAddress_Sub2();
  CheckAddress_Sub();
}
//静的変数 aと自動変数 bのアドレスを出力
void CheckAddress_Sub(){
  static int a;
  int b;
  std::cout << "&a = " << &a << std::endl
            << "&b = " << &b << std::endl;
}
//この関数の中から CheckAddress_Subを読んだときに
//変数aとbのアドレスがどうなるかチェック
void CheckAddress_Sub2(){
  std::cout << "in Sub2" << std::endl;
  CheckAddress_Sub();
}

//初期化が一回されないかのチェック

void CheckInitOnce_Sub();

void CheckInitOnce() {
  std::cout << std::endl << "初期化が一回しかされないかのチェック" << std::endl;

  CheckInitOnce_Sub();
  CheckInitOnce_Sub();
}

//++aと++bの影響が二度目以降の呼び出しに影響するかチェック

void CheckInitOnce_Sub() {
  static int a = 3;
  int b = 3;
  std::cout << "a = " << a << std::endl
            << "b = " << b << std::endl;
  ++a;
  ++b;
}

//0で初期化されるのかチェック
//　偶然０だったときのために変数を作って確かめる
//自動変数も一緒に確認

void CheckZeroInit_Sub();
void CheckZeroInit_Sub2();

void CheckZeroInit(){
  std::cout << std::endl << "０で初期化されるのかチェック" << std::endl;

  CheckZeroInit_Sub();
  CheckZeroInit_Sub2();
}

//静的変数がなにで初期化されるのかチェック
void CheckZeroInit_Sub(){
  static int a, b, c, d;
  std::cout << a << ',' << b << ',' << c << ',' << d << std::endl;
}

//自動変数がなにで初期化されるのか確認
void CheckZeroInit_Sub2(){
  int a, b, c, d;
  std::cout << a << ',' << b << ',' << c << ',' << d << std::endl;

}

//値が保証されるかのチェック

void CheckInvariant_Sub(int*& pa, int*& pb);
void CheckInvariant_Sub2();

void CheckInvariant(){
  std::cout << std::endl << "値が保証されるかのチェック" << std::endl;

  int *pa, *pb;
  CheckInvariant_Sub(pa,pb);
  CheckInvariant_Sub2();
  //CheckInvariant_Sub2を読んでもaとbの値が保存されているかチェック
  //ばああいによってあはチェック失敗するかも
  std::cout << "*pa = " << *pa << std::endl
            << "*pb = " << *pb << std::endl;
}

//静的変数 aと　自動変数bのアドテスを引数として通して返す
void CheckInvariant_Sub(int*& pa, int*& pb){
  static int a = 9;
  int b = 9;

  pa = &a;
  pb = &b;
}

//大きな変数を作っってソテをすべて０フェ埋める
//fill_mはしていしたデータをじゃおてりあなどｆで　いえっる関数
void CheckInvariant_Sub2(){
  int dummy[100];
  fill_n(dummy,100,0);

}

int main(){
  CheckAddress();
  CheckInitOnce();
  CheckZeroInit();
  CheckInvariant();
}

```
長すぎ。しんどい。
aのアドレスが一定なので静的ローカル変数になってる
二回目の呼び出し時にa =4なので一度しか初期化されていない。
初期化されなければ0で初期化
静的変数は関数を抜けても値が保存される。

#終わりに
明日はスコープ
今日は早めに寝る
おやすみなさい。