HOWTO · C++

遍歷 C++ 中的列表

這是一個關於 List 資料結構以及我們如何在 C++ 中遍歷 List 資料結構的簡單教程。

本頁內容

在 C++ 中走訪 std::list 時,先用 begin() 初始化迭代器;只要它不等於 end(),就處理目前元素並遞增迭代器。取值或修改目前值時,對迭代器解參考。迴圈會在 end() 之前停止;end() 是超出尾端的位置標記,不是指向最後一個元素的迭代器。

C++ 中的 std::list 是什麼?

std::list 是 C++ 標準函式庫中的雙向連結串列容器。元素存放在節點中,各節點彼此連結,因此不會像 std::vector 或陣列的元素那樣占用一整塊連續記憶體。這種結構支援雙向走訪;若已經有指向某個位置的迭代器,在該位置插入或移除元素的時間複雜度為常數。

串列不提供 items[4] 這類直接索引。若要取得指定位置的元素,必須逐步遞增迭代器走過串列,所需時間會與走訪距離成正比。每個元素除了值本身,也需要額外儲存連結資訊。當需要穩定的迭代器,或需要在已知位置插入、移除元素時,可選用 std::list;若重視儲存緊湊或經常依索引存取,通常使用 vector 會更簡單。

C++ 也提供另一種獨立的單向連結容器 std::forward_list,只能向前走訪。它與 std::list 是不同的容器。若想進一步了解,請參閱雙向連結串列文章。

如何走訪 C++ 的 std::list

begin() 傳回的迭代器指向第一個元素。end() 指向最後一個元素之後的位置,因此可用作迴圈的停止條件,但不可解參考。遞增迭代器即可前進到下一個元素。

執行以下範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。

#include <iostream>
#include <list>

int main() {
    std::list<int> scores{12, 18, 25};

    for (std::list<int>::iterator it = scores.begin(); it != scores.end(); ++it) {
        std::cout << *it << '\n';
    }
}
12
18
25

在這裡,it 從 scores.begin() 開始。每次迴圈都會用 *it 讀取目前值,再以 ++it 前進到下一個節點。當迭代器到達 scores.end() 時,條件便不成立,迴圈結束,也不會讀取超出尾端的位置。

透過非 const 迭代器,可以指定 *it 來修改元素。例如,在迴圈本體中加入 *it += 1;,就會增加目前元素的值。如果只需要逐一檢視值,可使用範圍式 for 迴圈:for (int score : scores)。若要用這種寫法修改值,請將每個項目繫結為參考:for (int& score : scores)。當需要使用迭代器本身時,例如移除目前位置的元素,則適合使用明確的迭代器迴圈。

走訪串列時若要刪除元素,請將 erase 傳回的迭代器指定回迭代器變數,便能從下一個元素繼續。刪除元素會使指向該元素的迭代器失效,但指向其他 std::list 元素的迭代器仍然有效。