範囲for文

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

for文と言えば、下記のようなものと思っていた。

for (int i = 0; i < 5; i++)
{
    std::cout << i << std::endl;
}

出力

0
1
2
3
4

が、今日こんなfor文を見た。

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

for (auto v : list)
{
    std::cout << v << std::endl;
}

これは何なのか?調べたい。

しらべたこと

この書き方は「Range-based for Statement (C++)」というらしい。

learn.microsoft.com

日本語では「範囲ベースの for 文 (C++)」と訳されていた。

こんな感じで書けた。

int main()
{
    // 配列に対して
    int list2[5] = { 6,7,8,9,10 };

    for (auto v : list2)
    {
        std::cout << v << std::endl;
    }

    // vectorに対して
    std::vector<int> list = {1,2,3,4,5};

    for (auto v : list)
    {
        std::cout << v << std::endl;
    }

    // 直接も書ける
    for (auto v : {11,12,13,14,15})
    {
        std::cout << v << std::endl;
    }
}

ただし、

for (auto v : list){}

という書き方は推奨されないらしい。
undesirableと書かれている)

推奨/非推奨がどれなのか

下記を見ながらどれがどうなのか書き出してみる。

https://learn.microsoft.com/ja-jp/cpp/cpp/range-based-for-statement-cpp?view=msvc-170

①配列のコピーを作ってしまうやり方(非推奨)

Copy of 'x', almost always undesirable

int list[5] = { 6,7,8,9,10 };

for (auto v : list)
{
    std::cout << v << std::endl;
}

②参照による型推論するやり方(値の変更をする場合に推奨)

Type inference by reference.
Observes and/or modifies in-place. Preferred when modify is needed.

int list[5] = { 6,7,8,9,10 };

for (auto &v : list)
{
    std::cout << v << std::endl;
}

③const参照による型推論するやり方(値の変更をしない場合に推奨)

Type inference by const reference.
Observes in-place. Preferred when no modify is needed.

int list[5] = { 6,7,8,9,10 };

for (const auto &v : list)
{
    std::cout << v << std::endl;
}

まとめ

配列の値の変更をするときは②、しないときは③のやり方で書けばよいっぽい。

参考

範囲ベースの for ステートメント (C++)

https://learn.microsoft.com/ja-jp/cpp/cpp/range-based-for-statement-cpp?view=msvc-170