前言
這邊要來整理長期我在 C++ 感到困惑的一個問題,
就是為什麼有時候 for 迴圈 會有 &,有時候 for 迴圈 又沒有 &,
然後有時候沒有 & 也跑得過,有時候看範例卻又不是這樣寫。
直接看程式碼再來解釋
下面這一段程式碼是一個簡化後的例子,它可以用來解釋我目前困惑的所有問題。
我們單純的讓程式印出從 0 到 9,
也宣告了另外一個 arr 從 9 一路到 0。
#include <iostream>
using namespace std;
int main()
{
for (int i = 0; i < 10; ++i)
{
cout << i;
}
cout << endl << "---------------------" << endl;
int arr[10] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
for (int i = 0; i < 10; ++i)
{
cout << arr[i];
}
cout << endl << "---------------------" << endl;
for (int* it = std::begin(arr); it != std::end(arr); ++it){
cout << it << ", "; // it: address
cout << *it << endl; // *it get value
}
cout << endl << "---------------------" << endl;
for (int &ele : arr)
{
cout << ele;
}
cout << endl << "---------------------" << endl;
return 0;
}
結果
解釋區
上面的程式碼大致分為四段,讓我理解了非常多的事情,還有觀念混淆的地方
第一段 for loop 的例子,最單純的數值增加
for (int i = 0; i < 10; ++i)
{
cout << i;
}
第一段例子是每一位學 c++ 新手都一定最早學到的例子,
他就是一個單純的數值增加,
但大部分開始混亂,都是從下面那幾個例子才開始出現的,例如我XD。
第二段 for loop 的例子,我們是在用 for 增加變數,透過變數去拿取物件
int arr[10] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
for (int i = 0; i < 10; ++i)
{
cout << arr[i];
}
到這裡應該也還不算太混亂,就只是一個透過 array 的 index 去拿取對應的 arr 數值。
第三段 for loop 的例子 (重要),其實,我們是直接去地址拿值!
for (int* it = std::begin(arr); it != std::end(arr); ++it){
cout << it << ", "; // it: address
cout << *it << endl; // *it get value
}
讓我觀念開始混亂,就是從這個例子開始的,
碰到 array 數值的拿取,第二種寫法或是第三種寫法都是主流,
- 第二種寫法是透過「index」去拿取 arr 裡面的值
- 第三種寫法是,「我們直接去對應的記憶體位置,把值拿出來」
所以這邊我們看到 for 開頭宣告是指標的 int,
因為我們是透過這個 int,作為 iterator 去遍歷我們的 array 的內容。而這裡還有一個重要的觀念,注意輸出結果的部分,我們發現儲存的記憶體位置,
每一次都是移動 4 個 bytes,並且連續。我們唯有透過正確的一次移動 4 bytes 的記憶體位置,才能夠拿到正確的值。
(而我們怎麼知道「記憶體位置正確的移動」是 4 bytes? 注意到我們 iterator 定義的是 int* 了嗎! )
而這個例子,經常有的延伸應用
通常這樣子的寫法會被我們拿來遍歷各種更複雜的資料結構,例如像是 vector…
這也是為什麼我們在 for 的後面,必須要宣告一個指標的原因,
實際上我們就是在不斷地移動記憶體位置,好讓我們去拿取對應的值。
第四段 for loop 的例子 (重要),其實,我們也是直接去地址拿值!
第四種寫法出現後,更是讓我跟前面的第二、三個例子,整個大爆炸!!!
這也是為什麼這次整理,一開始就在強調,
現在就是要整理 for 迴圈後面出現的東西,
為什麼有時候有 * ? 有 & ?
他們一起出現的時