初心者が C++ を勉強するときに最低限押さえておいたほうがよい C++11/14 の機能

[ブログ記事](http://secret-garden.hatenablog.com/entry/2015/12/01/204727)からの転載です。
この記事は[初心者 C++er Advent Calendar 2015](http://www.adventar.org/calendars/922)の1日目の記事になります。  
本アドベントカレンダーはまだ空きがあるので気になる方は参加してみるとよいと思います。
<br>
さて、最近だと C++11/14 で書かれている本も増えてきたんですが、やっぱり昔の入門書だとどうしても C++03 が中心になってしまっていてちょっとつらいんですよねー。  
と、いうわけで『これから C++ をはじめてみたい！』という人に知っておいてほしい（抑えておいてほしい）C++11/14 の言語機能をちょっとまとめてみました。

## C++11/14 を始める前に

C++ ではコンパイラやバージョンによって実装されている C++11/14 の機能がまちまちです。  
そのため、今回紹介した機能が手元の環境では動作しない可能性もあります。  
単に機能を試すだけであれはオンラインコンパイラの[Wandbox](http://melpon.org/wandbox/)で試してみるとよいかと思います。  

## nullptr (C++11)

みんな大好き `NULL` は C++11 から `nullptr` というキーワードとして追加されました。  
基本的な使い方は `NULL` と同じですが、`NULL` と比べてより安全に利用することができます。  

```cpp
int a = 42;

// NULL は 0 として定義されているのでこういう比較ができてしまう
if( a == NULL ){
	...
}

// nullptr はポインタ型でのみ比較するのでこれはエラーになる
if( a == nullptr ){
	...
}
```

## 2進数リテラル (C++14)

コンパイラによっては独自拡張として実装されていた2進数リテラルが C++14 でやっと正式に導入されました。  
これは `0b` を数値のプレフィックスすることで2進数を記述する事ができます。  

```cpp
int a = 0b11;         // 3
int b = 0b1011;       // 11
int c = 0b10101101;   // 173
```

## 数値リテラルの区切り (C++14)

C++14 では整数リテラルと浮動小数点リテラルを任意の桁で区切ることができるようになりました。  
区切り文字はシングルクオート（`''`）になります。

```cpp
auto n = 1'000'000;
auto pi = 3.1415'9265'359;
```


## 型推論 (C++11/14)

C++11 から `auto` というキーワードが追加されました（正確に言えば C++11 以前からも別の用途として存在していましたが。
これを利用することで型名を明示的に定義しなくても右辺値から型を推論することで型名の記述を省略する事ができます。

```cpp
// 以前は以下のように記述する必要がった
// std::vector<int>::const_iterator it = v.cbegin();
// auto を利用することでコードの冗長性を省くことができる
auto it = v.cbegin();
```

また、C++14 では以下のように関数の戻り値型にも `auto` を使用することができます。

```cpp
template<typename T, typename U>
auto
plus(T t, U u){
	return t + u;
}

auto result = plus(1, 2);		// int 型
auto result = plus(1, 3.14);	// double 型


// ちなみに C++11 でも以下のようにすれば関数の戻り値型に auto を使用することも可能
// template<typename T, typename U>
// auto
// plus(T t, U u)
// ->decltype(t + u){
//     return t + u;
// }
```

## 初期化リスト (C++11)

初期化リストとは配列などを初期化するときに使用する機能(`{1, 2, 3}` みたいなの)です。

```cpp
int array[] = {1, 2, 3, 4, 5};
```

C++11 ではこの機能が強化され、`std::vector` や `std::map` などを簡単に初期化することができるようになりました。  

```cpp
// 配列と同じような感じで初期化することができる
std::vector<int> v = {1, 2, 3, 4, 5};


// std::map もこんな感じで初期化できる
std::map<int, std::string> table = {
	{1, "homu"},
	{2, "mami"},
	{3, "mado"},
};


std::pair<std::string, std::string>
swapping(std::pair<std::string, std::string> p){
	// 関数の戻り値に対しても適用できる
	// std::pair<std::string, std::string>{ p.second, p.first }
	// みたいに書かなくてもよい
	return { p.second, p.first };
}

// 引数に直接渡すこともできる
swapping({"homu", "mami"});
```

## 範囲 for ループ (C++11)

C++11 では範囲 for ループが実装され、配列や標準ライブラリのいくつかのコンテナを簡単にイテレートすることができるようなりました。

```cpp
std::vector<int> v = {1, 2, 3, 4, 5};

// for(型 変数名 : コンテナ){ ... } という風にループする事ができる
for(int var : v){
	std::cout << var << std::endl;
}
// 以下のように書くのと同等
// for(auto it = std::begin(v) ; it != std::end(v) ; ++it){
// 	int var = *it;
// 	std::cout << var << std::endl;
// }

std::map<int, std::string> table = {
	{1, "homu"},
	{2, "mami"},
	{3, "mado"},
};

// 型名に auto を使用することもできる
for(auto p : table){
	std::cout << p.first << " : " << p.second << std::endl;
}
```

## 非静的メンバ初期化 (C++11)

C++11 では次のようにしてメンバ変数の定義時に初期値を設定することができます。

```cpp
struct person{
	// メンバ変数の定義時に初期値が設定できる
    std::string name = "homu";
    int age = 14;
};
```

これは

```cpp
struct person{
    std::string name;
    int age;

	person() : name("homu"), age(14){}
};
```

と定義しているのと同等になります。

## 明示的な仮想関数オーバーライド (C++11)

C++ で仮想関数をオーバーライドする場合、誤って別の型で定義してしまう可能性があります。

```cpp
struct base{
	virtual void func(int);
};

struct derived : base{
	// base::func() をオーバーライドしたかったが誤って引数を間違えた
	virtual void func(float);
};
```

上記の場合は意図とは異なるのにも関わらずエラーにならずコンパイルが通ってしまします。  
これを抑止するために C++11 から `override` というキーワードが追加されました。  
次のように `override` キーワードを追加することで明示的に『オーバーライド先と一致するか』のチェックを行うことができます。

```cpp
struct base{
	virtual void func(int);
};

struct derived : base{
	// override を追加することで明示的に
	// 基底クラスの仮想関数をオーバーライドすると宣言する
	// この定義では基底クラスの仮想関数と引数型が異なるので
	// コンパイルエラーになる
	virtual void func(float) override;
};
```

このように `override` を使用することで誤った定義を抑止する事ができます。  
また、`override` の他に `final` というキーワードも追加されました。  
`final` は仮想関数やクラス定義時に追加して記述する事ができます。  
前者は基底クラスでオーバーライドするとエラーになります。

```cpp
struct base{
	virtual void func(int);
};

struct derived : base{
	virtual void func(int) final;
};

struct derived2 : derived{
	// derived::func() に final が付いている為
	// オーバーライドしようとするとエラーになる
	virtual void func(int);
};
```

後者は基底クラスに指定した場合にエラーとなります。

```
struct X final{};

// X は final が付いているので継承しようとするとエラーになる
struct derived : X{};
```

このように `override` や `final` を使用することでより堅牢にクラスや仮想関数を定義することができます。


## raw文字列リテラル (C++11)

C++11 で追加された raw文字列リテラルを使用することで `"` や `\` などの特殊文字のエスケープや改行などをそのまま文字列として記述する事ができます。

```cpp
// R"delimiter( から )delimiter" までが文字となる
// また "delimiter" という文字列は任意の文字列が使える
// 文字列内で改行したりタブ文字を挿入した場合はそのままの形で出力される
auto str = R"delimiter(homu
	mado
"mami"
saya \ an
)delimiter";

std::cout << str << std::endl;
/* output
homu
	mado
"mami"
saya \ an

*/
```


## まとめ

と、いうことですがざっくりと初心者向けかな？という機能をまとめてみました。  
特に『型推論』、『初期化リスト』、『範囲 for ループ』などは C++ を始めた頃に結構使うような機能だと思います。  
C++ はよく複雑で難しい言語だと言われていますが、個人的には C++11/14 になってだいぶ取っ付き易い言語になってきてると思います。  
今後 C++17 も控えていますし、C++ を勉強しようと思ってるひとはいまがチャンスな気がするので積極的に学んで見るとよいと思います。  
ちなみに C++11/14 というとよく『ラムダ式』や『`constexpr`』、『右辺値参照』、『可変長引数テンプレート』などと言ったものが取り上げられるんですが、そのあたりの機能はあまり初心者向けではないので今回は省きました。