C++基於範圍的for迴圈詳解

2020-07-16 10:04:37
C++ 11提供了一個特殊版本的 for 迴圈,在很多情況下,它都可以簡化陣列的處理,這就是基於範圍的 for 迴圈。在使用基於範圍的 for 迴圈處理陣列時,該迴圈可以自動為陣列中的每個元素疊代一次。

例如,如果對一個 8 元素的陣列使用基於範圍的 for 迴圈,則該迴圈將疊代 8 次。因為基於範圍的 for 迴圈可以自動知道陣列中元素的個數,所以不必使用計數器變數控制其疊代,也不必擔心陣列下標越界的問題。

基於範圍的 for 迴圈使用了一個稱為範圍變數的內建變數。每次基於範圍的 for 迴圈疊代時,它都會複製下一個陣列元素到範圍變數。例如,第一次迴圈疊代,範圍變數將包含元素 0 的值;第二次迴圈疊代,範圍變數將包含元素 1 的值,以此類推。

以下是基於範圍的 for 迴圈的一般格式:

for (dataType rangeVariable : array)
    statement;

現在來仔細看一看該格式的各個部分:
  • dataType:是範圍變數的資料型別。它必須與陣列元素的資料型別一樣,或者是陣列元素可以自動轉換過來的型別。
  • rangeVariable:是範圍變數的名稱。該變數將在迴圈疊代期間接收不同陣列元素的值。在第一次迴圈疊代期間,它接收的是第一個元素的值;在第二次迴圈疊代期間,它接收的是第二個元素的值;以此類推。
  • array:是要讓該迴圈進行處理的陣列的名稱。該迴圈將對陣列中的每個元素疊代一次。
  • statement:是在每次回圈疊代期間要執行的語句。要在迴圈中執行更多的語句,則可以使用一組大括號來包圍多個語句。

例如,假設已經定義了以下陣列:

int numbers[] = {3, 6, 9};

可以使用基於範圍的 for 迴圈來顯示 numbers 陣列的內容。語句如下:
for(int val : numbers)
{
    cout << "The next value is ";
    cout << val << endl;
}
因為 numbers 陣列有 3 個元素,所以該迴圈將疊代 3 次。第一次它疊代時,val 變數將接收 numbers[0] 中的值;在第二次迴圈疊代期間,它將接收 numbers[1] 的值;在第三次迴圈疊代期間,它將接收 numbers[2] 的值。

所以,該程式碼將產生以下輸出結果:

The next value is 3
The next value is 6
The next value is 9

如果需要的話,可以使用 auto 關鍵字指定範圍變數的資料型別,而不必手動指定,範例如下:
for (auto val : numbers)
{
    cout << "The next value is ";
    cout << val << endl;
}
下面的程式使用了基於範圍的 for 迴圈來顯示一個 string 變數的元素。
//This program demonstrates the range-based for loop
#include <iostream>
#include <string>
using namespace std;

int main ()
{
    string planets []= { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto(a dwarf planet)" };
    // Display the values in the array
    cout << "Here are the planets: n ";
    for (string val : planets)
        cout << val << endl;
    return 0;
}
程式輸出結果為:

Here are the planets:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
Pluto(a dwarf planet)

使用基於範圍的 for 迴圈來修改陣列

當基於範圍的 for 迴圈執行時,其範圍變數將僅包含一個陣列元素的副本。因此,不能使用基於範圍的 for 迴圈來修改陣列的內容,除非將範圍變數宣告為一個參照。參照變數是其他值的一個別名,任何對於參照變數的修改都將實際作用於別名所代表的值。

要將範圍變數宣告為參照變數,可以在迴圈頭的範圍變數名稱前面新增一個 & 符號。下面程式即顯示了這樣一個範例,它使用了基於範圍的 for 迴圈來將使用者輸入的資料儲存到一個陣列中。
//This program uses a range-based for loop
//to modify the contents of an array.
#include <iostream>
using namespace std;

int main ()
{
    const int SIZE = 5;
    int numbers[SIZE];
    //Get values for the array.
    for (int &val : numbers)
    {
        cout << "Enter an integer value: ";
        cin >> val;
    }
    // Display the values in the array.
    cout << "nHere are the values you entered: n";
    for (int val : numbers)
        cout << val << " ";
    cout << endl;
    return 0;
}
程式輸出結果:

Enter an integer value: 10
Enter an integer value: 20
Enter an integer value: 30
Enter an integer value: 40
Enter an integer value: 50

Here are the values you entered:
10 20 30 40 50

請注意範圍變數 val,在它的名稱前面有一個 & 符號,這表示它被宣告為參照變數。當迴圈執行時,val 變數將不再只是陣列元素的副本,而是變成了元素本身的別名。因此,對 val 變數作出的任何修改都會實際作用於它當前參照的陣列元素。

相比之下,第 20 行中的變數名前面就沒有 & 符號,這是因為在此無須將 val 宣告為參照變數。該迴圈只是要顯示陣列元素,而不是改變它們。

基於範圍的 for 迴圈和常規 for 迴圈對比

基於範圍的 for 迴圈可用於需要遍歷陣列所有元素的任何情形,並且不需要使用元素下標。但是,如果出於某些目的需要使用元素下標時,基於範圍的 for 迴圈就不能使用了。另外,如果迴圈控制變數被用於存取兩個或兩個以上不同陣列的元素,那麼它也不適合使用。在這些情況下,可以使用常規 for 迴圈。

注意,參照範圍變數也可以使用 auto 關鍵字。例如,上面程式中的 for 迴圈也可以寫成如下的形式:
for (auto &val : numbers)
{
    cout << "Enter an integer value: ";
    cin >> val;
}