初めましての方は初めまして、そうでない方はこんにちは。DtYaZsKです。
この記事は
KMC Advent Calendar 2013の22日目の記事です。
昨日はwackyさんの
東アジア文字幅問題との戦いの記録でした。
今回はISO/IEC 14882:2011、通称C++11で追加されたC++の新しい要素の内私が独断と偏見で選んだものを5つほど簡単に説明します。
C++11超入門と銘打っていますがそれ以前のC++、所謂C++03までの知識、特にtemplateとポインタとSTLの基礎知識は前提としています。
怖いC++erの方々にとってはすでに知ってる内容ですし、逆にC++のことがさっぱりな方にとっては意味不明な内容かもしれません。
今回やる内容はgccやclangではもちろん、VC++でも使うことが出来ます。そのため最近のC++コンパイラならすぐに使えるものばかりです。(VC++はC++のコンパイラではないというツッコミは今回放置しておきます。)
最新のコンパイラを用意するのが面倒な方にも朗報です。今の時代はオンラインコンパイラが存在するのですぐに最新のC++を体感することができます。私は
Wandboxをよく使っています。
また標準ライブラリのリファレンスは
cpprefjpをよく使っています。今回の記事はこのページを参考にしました。
12/22 23:55追記 記事の一部が間違っていることに今更気づいたので該当部分を削除しました1.スマートポインタ
newで動的にメモリを確保した時それを解放するためにdeleteを書くのは面倒ですし書き忘れでメモリリークを起こすと大変です。
不要なメモリを自動で開放してくれる仕組みがあればそのような問題を解決できます。
そのような仕組みを持つ賢いポインタをスマートポインタといいます。
C++11にはスマートポインタであるshared_ptrとunique_ptrが存在します。
これら2つのクラスは共にmemoryヘッダをincludeすることで使えるようになります。
共にコンストラクタでポインタを受け取りますが
shared_ptrには補助関数がありそちらの方が効率的です。
ヌルポインタでないポインタを保持している場合デストラクタで条件を満たせば開放します。
これら2つの違いはコピー可能かどうかです。
shared_ptrは参照カウント方式のスマートポインタです。すなわち自分が参照されている数をカウントし0になったら自動で開放します。
一方unique_ptrはコピー不可能なスマートポインタです。コピーしようとするような文が含まれている場合コンパイルエラーとなります。よってデストラクタで確実に開放します。(ヌルポインタ保持時除く)
shared_ptr同士、unique_ptr同士なら中身を交換できますし
中身をリセットすることもできます。
要素のアクセスについてですがoperator->とoperator*がオーバーロードされているので普通のポインタのように要素にアクセスできます。
関連した話でC++11ではヌルポインタ専用リテラルnullptrが追加されています。
なお今回weak_ptrの説明は省きました。
またC++14ではmake_sharedのunique_ptr版、make_uniqueが追加されます。
2.array
STLに静的配列が追加されました。arrayです。いうならば普通の配列のラッパーです。arrayヘッダをincludeすることで使えます。
テンプレート引数で格納する型と要素数を指定できます。
使い方も普通の配列と変わりません。
配列でなくてarrayを使う利点はalgorithmヘッダの関数を用いることができることです。
他にも要素をまるまる入れ替えたり範囲チェックつきアクセスも出来ます。
3.randomヘッダ
Cの時代から擬似乱数生成の関数は存在しました。randです。この関数には2つ問題点がありました。
一つは生成される数値の範囲が狭いこと。もう一つは線形合同法を用いているため結果のランダム性が低いこと。
C++11では独自の擬似乱数生成法を持つことができました。それがrandomヘッダです。
randomヘッダでは擬似乱数生成のためのクラスが用意されています。
例えばmt19937クラスはメルセンヌツイスター法で32bit長符号なし整数型乱数を生成します。
初期化にはrandom_deviceクラスを用いることが出来ます。これはハードウェアの状態によって決める本物の乱数です。
ハードウェアの情報を読み取るためrandom_deviceはその他の乱数生成クラスに比べ遅めです。
よってメインでは擬似乱数生成クラスを用い、初期化にはrandom_deviceを使うのが一つの定型です。
他にもrandomヘッダには上のような擬似乱数生成クラスを用いたオプションが用意されています。
例えばuniform_int_distributionクラスは指定範囲の整数を等確率で返してくれます。
bernoulli_distributionは指定された確率でtrueを、trueでないときはfalseを返してくれます。
他にもrandomヘッダには様々なクラスが存在しますが、全てを紹介するには時間が足りません。
4.autoとdecltype
しばしば型の名前を書くのが面倒になるような型が存在します。
C++11ではコンパイラが型を判別し自動で変数、または関数の型を決定してくれる方法が2つ存在します。
もう一つはauto、もう一つはdecltypeです。
autoは=の右辺値の型によって左辺値の型を決定します。一方decltypeは関数に似た使い方をし引数として渡されたオブジェクトやリテラルによって型を決定します。
以下を見ればだいたい理解できると思います。
5.範囲ベースのfor文
配列の要素に対して1つずつ同じ処理をしていきたい時があります。
別に普通のfor文を使えばいいのですがカウント用の変数を使わないなら範囲外アクセスが怖いだけですよね。
C++11では配列の範囲を基準とした新たなfor文ができました。
使い方は以下を見ればわかると思います。
配列だけでなくSTLにも使えます。
参照でない場合は要素をそれぞれコピーして処理します。
C++11では言語仕様も標準ライブラリもC++03に比べはるかに強化されました。
今回の記事で扱った内容でもまだまだ氷山の一角です。
C++11の全てを扱うにはこのブログではキャパ不足かもしれません。
この記事をきっかけに少しでもC++11について学ぼうと考える方が増えることが私の願いです。
明日はhatsusatoさんのC++11で覚醒した共用体の話です。
PR