はじめに

編集

この章では、C++の範囲ベースforループの使い方を解説します。

範囲ベースforループはC++11で導入され、従来のforループよりもシンプルにコンテナや配列の要素を反復処理できます。基本構文から応用まで、実用的な情報を紹介します。

範囲ベースforループの基礎

編集

概要

編集

範囲ベースforループは、C++11で追加された構文で、コンテナや配列の要素を簡潔に処理できます。インデックスやイテレータの管理が不要になり、コードの可読性が向上します。

基本構文

編集
for (const auto& element : container) {
    // 処理内容
}

containerはイテレートする対象、elementは要素を指します。変更不要ならconst修飾子を使用します。

応用

編集

対応データ構造

編集
配列
配列はそのまま使用可能です。
int array[] = {1, 2, 3, 4, 5};
for (auto element : array) {
    // 処理
}
STLコンテナ
std::vectorstd::listなどに対応。
std::vector<int> vec = {1, 2, 3, 4, 5};
for (auto element : vec) {
    // 処理
}

入れ子構造への適用

編集

多次元データにも利用できます。

std::vector<std::vector<int>> matrix = {{1, 2}, {3, 4}, {5, 6}};
for (const auto& row : matrix) {
    for (auto element : row) {
        // 処理
    }
}

参照を使って要素の変更

編集

要素を変更するには参照を使用します。

std::vector<int> numbers = {1, 2, 3, 4, 5};
for (int& num : numbers) {
    num *= 2;
}

イテレータと範囲ベースforループ

編集

イテレータは、C++において様々なコンテナの要素にアクセスするための重要な概念です。範囲ベースforループは、このイテレータの仕組みを抽象化し、より直感的なループ処理を可能にします。

イテレータの基本

編集

イテレータは、ポインタのように振る舞うオブジェクトで、コンテナの要素を順番に走査するために使用されます。主な標準イテレータには以下のようなものがあります:

begin()
コンテナの最初の要素を指すイテレータを返します。
end()
コンテナの最後の要素の次を指すイテレータを返します。
auto vec = std::vector{1, 2, 3, 4, 5};
auto it = vec.begin();  // 最初の要素を指すイテレータ
auto end_it = vec.end();  // 最後の要素の次を指すイテレータ

範囲ベースforループとイテレータの関係

編集

範囲ベースforループは、内部的にイテレータを使用して動作します。次の例は、従来のイテレータを使用したforループと範囲ベースforループの等価な動作を示しています:

#include <iostream>
#include <vector>

auto main() -> int {
    auto numbers = std::vector{1, 2, 3, 4, 5};

    // 従来のイテレータを使用したforループ
    for (std::vector<int>::iterator it = numbers.begin(); it != numbers.end(); it++) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 同等の範囲ベースforループ
    for (const int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    return 0;
}

カスタムイテレータのサポート

編集

範囲ベースforループは、begin()end()メンバー関数、またはフリー関数を持つカスタムコンテナでも使用できます:

#include <iostream>

class CustomContainer {
   public:
    auto begin() -> int* { return data; }
    auto end() -> int* { return data + size; }

   private:
    int data[5] = {1, 2, 3, 4, 5};
    int size = 5;
};

auto main() -> int {
    CustomContainer myContainer;
    for (const auto value : myContainer) {         
        std::cout << value << " ";
    }
    return 0;
}

注意点

編集
イテレータの有効性
ループ中にコンテナを変更すると、イテレータが無効化される可能性があります。
パフォーマンス
範囲ベースforループは通常、従来のforループと同等のパフォーマンスを持ちます。
参照の使用
大きな構造体や変更を伴う処理では、参照を使用することで効率的になります。
std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
for (const auto& name : names) {  // 参照を使用
    // 効率的な処理
}

メリットと注意点

編集

範囲ベースforループは可読性や安全性を向上させますが、ループ内でイテレータを無効化しないよう注意が必要です。