今すぐに使いたいC++11の新機能


このエントリーをはてなブックマークに追加

最近導入の敷居が下がってきたC++11に興味が湧いてきた。C++11の新機能を眺めてみると、正直半分くらいの項目はよく理解できないのだが、いくつかの項目は"Better C++"としていますぐにでも使いたいものであった。今回は導入の効果が高そうなC++11の新機能を紹介する。

autoによる型推論

C++03以前では、必ず変数の宣言時に型を指定しなければいけなかった。そのため、例えばSTLイテレーションを回すときには以下のように長ったらしい書き方をしなければいけなかった。

map<int, int> m;
...
for(map<int, int>::iterator it = m.begin(); it != m.end(); ++it)
{
...
}

ここでmの型をmapに変更すると、それにともなってイテレーションの型もmap::iteratorに変更しなければならず大変面倒くさかった。


C++11では、itの型を明示的に示す必要がなく、以下のように書ける。
以下のコードでは従来のm.begin()/m.end()を使ってもよいが、後述するようにbegin(m)/end(m)を使うのがC++11流らしい。

for(auto it = begin(m); it != end(m); ++it)

使える所ではできるだけautoを使うのがC++11流らしい。

Foreach

スクリプト言語でおなじみのForeach(正式名称はRange-based for loop(範囲に基づくforループ))が導入された。これは欲しかった機能。

#include <iostream>
#include <vector>

using namespace std;

int main(){
    vector<int> vec;
    vec.push_back( 55 );
    vec.push_back( 66 );
    vec.push_back( 77 );

    for( auto el : vec ){
        cout << el << endl;
    }
    return 0;
}

参照を使うと中身をいじることもできる。

for( auto &el : vec ){
    el += 10000;
}


普通の配列に対しても使える。

int array[] = { 1, 2, 3, 4, 5 };
for (auto n : array) {
    cout << n << endl;
}

以下のように、名前のない配列を使うこともできる。ここまでくるともはやC++には見えない。

for (auto n : {1, 2, 3, 4, 5}) {
    cout << n << endl;
}

std::begin(), std::end()

C++03以前では、コンテナに対してループをかけるとき、コンテナが持つメンバ関数begin()とend()を使うことになっていた。

sort( v.begin(), v.end() );

C++11ではstd::begin()とstd::end()を使うことが推奨される。

sort( begin(v), end(v) );

std::begin()とstd::end()は普通の配列に対しても以下のように使えるので便利である。

int numbers[] = { 9, 5, 1, 7, 3 };
sort(begin(numbers), end(numbers));

{}による初期化

C++03以前では、vector変数やmap変数の宣言時に任意の値を設定することができなかったが、C++11ではできるようになった。

int a[] {1, 2, 3, 4};
vector<int> vec {1, 2, 3, 4};
map<string, int> m {{"aaa", 10}, {"bbb", 20}, {"ccc", 30}};

イコールをいれてもよいようだ。どちらが普通なのだろうか。

int a[] = {1, 2, 3, 4};
vector<int> vec = {1, 2, 3, 4};
map<string, int> m = {{"aaa", 10}, {"bbb", 20}, {"ccc", 30}};

参考記事