C++の範囲ベースforループ(Range-based for)を徹底解説!構文から実例まで
範囲ベースforループ(range-based for loop)は、C++11で標準に追加された機能で、従来のforループをより簡潔に記述できる形式です。コンテナ内の要素を先頭から末尾まで順番に処理する際に活躍します。本記事では、その構文や使い方、メリット・デメリット、具体的なコード例まで詳しく解説します。
基本構文
for( range-declaration : range-expression ) loop statement
range-declaration(範囲宣言) ― range-expressionの要素と同じ型の変数宣言です。通常はautoキーワードを使うことで、要素の型を自動的に推論させることができます。
range-expression(範囲式) ― 要素のシーケンスを表す任意の式です。波括弧 {} で囲んだ初期化リストも使用できます。
loop-statement(ループ文) ― 範囲式の終端に達するまで繰り返し実行される、1つ以上の文からなるループ本体です。
従来のforループとの比較
// 配列を走査する
int arr[] = { 10,20,30,40,50 };
for (int num : arr)
printf("%d, ",num);
// 上記は以下と同等:
for ( int i=0;i<5;i++ )
printf("%d, ",arr[i]);
この比較を見ると、範囲ベースforループでは配列のサイズを計算する必要がなく、条件式も不要であることがわかります。また、インクリメント・デクリメント操作も必要ありません。各反復処理において、変数numには配列arr[]の要素が先頭から順に代入されていきます。ジャンプ文が実行されない限り、どの要素もスキップされることはありません。
ジャンプ文による制御
break ― 残りのすべての反復処理を中断し、ループを終了します。
continue ― 現在の反復処理をスキップし、次の反復へ移行します。
goto ― ループ外のラベル付きステートメントへジャンプします。
範囲ベースforのメリット
構文がシンプルで使いやすい。
コンテナの要素数や範囲式のサイズを計算する必要がない。
要素の型が不明な場合はauto指定子を使えば、range-expressionの型に自動的に対応できる。
条件式やインクリメント/デクリメント文が不要。
コンテナ全体を一括で走査したい場合に最適。
範囲ベースforのデメリット
begin()からend()までのすべての要素を走査するため、特定のインデックスだけを扱うことができない。
特定の要素を再訪問したり、一部の要素群をスキップしたりすることができない。
配列を逆順に走査できない。逆順処理には <boost/range/adaptor/reversed.hpp> ライブラリを使用する必要がある。
サンプルコード
#include <iostream>
#include <vector>
#include <map>
int main(){
int arr[] = { 10,20,30,40,50 };
// 従来のforループ
for ( int i=0;i<5;i++ )
printf("%d, ",arr[i]);
printf("\n");
// 範囲ベースforループ
for (int num : arr)
printf("%d, ",num);
printf("\n");
// 文字配列の場合
char str[] = "Hello World";
for (char c : str)
printf("%c ",c);
printf("\n");
for (char c : "Hello World")
printf("%c ",c);
printf("\n");
// std::mapの場合
std::map <int, char> MAP({{1, 'A'}, {2, 'B'}, {3, 'C'}});
for (auto m : MAP)
printf("{ %d, %c }", m.first,m.second);
}
実行結果
10, 20, 30, 40, 50,
10, 20, 30, 40, 50,
H e l l o W o r l d
H e l l o W o r l d
{ 1, A }{ 2, B }{ 3, C }
このように、範囲ベースforループは整数配列はもちろん、文字列やstd::mapなどのSTLコンテナにもそのまま適用できます。autoを使えばキーと値のペアも簡単に取り出せるため、モダンC++のコードを書く上で欠かせない機能といえるでしょう。
-
C++でピラミッドの体積を計算するプログラムの作り方|底面の形状別の公式と実装例
ピラミッドの底面の種類に応じた辺の長さが与えられたとき、そのピラミッドの体積を計算するのが本記事のテーマです。 ピラミッドとは、外側の面がすべて三角形で構成され、それらが共通の一点(頂点)で交わることで鋭い角を形成する3次元図形です。ピラミッドの体積は、底面がどのような形状であるかによって異なります。 ピラミッドの底面にはさまざまな種類があり、代表的なものは以下の通りです。 底面の形状別の体積の求め方 三角形の底面(三角錐) 底面が三角形の場合、ピラミッドの体積は次の公式で求められます。 体積 = (1/6) × a × b × h 正方形の底面(四角錐) 底面が正方形の場合、ピラミッドの体
-
C++で学ぶクイックソート(QuickSort)の仕組みと実装方法
クイックソートとはクイックソート(Quicksort)は、比較に基づいて未ソートのリスト(配列)を並べ替えるソートアルゴリズムの一つです。「パーティション交換ソート(partition exchange sort)」とも呼ばれます。クイックソートは安定ソートではありません。これは、等しい値を持つ要素同士の相対的な順序が保持されないためです。ただし、配列に対してごくわずかな追加メモリだけで動作するため、メモリ効率に優れています。選択ソートと非常に似ていますが、常に最悪のパーティションを選んでしまうわけではない点が異なり、より洗練された形の選択ソートと捉えることもできます。クイックソートは最も効率