目錄
1.list的介紹
2.list的使用
2.1 構造函數
2.2 iterator 的使用
2.3 容量操作
2.4 元素訪問
2.5 增刪查改
2.5.1頭插頭刪與尾插尾刪
2.5.2 insert 、erase 函數
2.5.3 clear、swap函數
2.5.4 關于find函數
3.迭代器失效
1.list的介紹
(1)list的底層通常實現為帶頭雙向循環鏈表,支持在任意位置插入、刪除
(2)鏈表中,每個節點包含:一個存儲數據的變量和指向前后兩個節點的指針
假設節點存儲的是int型的數據,則結構如下:
2.list的使用
詳細了解請參考文檔list - C++ Reference
下面只介紹一些常見接口:
2.1 構造函數
std::list() | 默認構造函數,創建一個空鏈表。 | std::list<int> l1; |
| 創建一個包含?n ?個元素的鏈表,所有元素初始化為?val 。 | std::list<int> l3(3, 10); ?→?{10, 10, 10} |
template<class InputIt>
| 使用迭代器范圍?[first, last) ?初始化鏈表(拷貝范圍內的元素)。 | std::list<int> l4(v.begin(), v.end()); (假設?v ?是?{1, 2, 3} ) |
std::list(const list& other) | 拷貝構造函數,創建一個與?other ?內容相同的鏈表(深拷貝)。 | std::list<int> l5(l4); (l5 ?內容與?l4 ?相同) |
2.2 iterator 的使用
begin() | 返回指向鏈表第一個元素的迭代器(若鏈表為空,返回?end() )。 | 正向遍歷鏈表、插入/刪除頭部元素、作為范圍循環的起點。 | ||
end() | 返回指向鏈表尾后位置的迭代器(不指向任何有效元素,僅用于比較)。 | 標記遍歷結束位置、作為范圍循環的終點、檢查鏈表是否為空(l.begin() == l.end() )。 | ||
rbegin() | 返回指向鏈表最后一個元素的反向迭代器(邏輯上為鏈表的“反向開頭”)。 | 反向遍歷鏈表、從末尾開始處理元素。 | ||
rend() | 返回指向鏈表“反向尾后”位置的迭代器(邏輯上為鏈表的“反向末尾”)。 | 標記反向遍歷結束位置、作為反向范圍循環的終點。 |
假設鏈表被實現為 帶頭雙向循環鏈表,則迭代器示意如下
總結:
1. begin與end為正向迭代器,對迭代器執行++操作,迭代器向后移動?
2. rbegin與rend為反向迭代器,對迭代器執行++操作,迭代器向前移動
2.3 容量操作
empty() | bool | 檢查鏈表是否為空(無元素) | if (l.empty()) { std::cout << "鏈表為空!"; } | ||
size() | size_type | 返回鏈表中元素的數量(類型為?std::size_t ) | std::cout << "鏈表大小: " << l.size(); |
2.4 元素訪問
front() | 返回鏈表第一個元素的引用 (可修改或讀取)。 |
或? | ||||
back() | 返回鏈表最后一個元素的引用 (可修改或讀取)。 |
或? |
2.5 增刪查改
2.5.1頭插頭刪與尾插尾刪
void push_front(const T& value); ? | 在鏈表頭部插入元素 | lt.push_front(1); | ||||||
void pop_front(); | 刪除鏈表頭部元素。 | lt.pop_front(); | ||||||
void push_back(const T& value); ? | 在鏈表尾部插入元素 | lt.push_back(1); | ||||||
void pop_back(); | 刪除鏈表尾部元素。 | lt.pop_back(); |
pop_front使begin()迭代器失效,pop_back使end()迭代器失效
其余的不失效
2.5.2 insert 、erase 函數
insert | 在指定位置?pos ?前插入元素(支持單元素、重復元素、范圍插入) | 返回指向新插入元素的迭代器(對單元素插入) | 原有迭代器不失效 | |||||
erase | 刪除指定位置或范圍的元素(支持單元素刪除、范圍刪除) | 返回指向被刪除元素后一個位置的迭代器。 | 使被刪除元素的迭代器失效 |
void test1(){std::list<int> lst = {1, 2, 3, 4, 5};// 1. 單元素插入(在第二個位置插入 99)auto it = lst.begin();// 手動移動迭代器到第二個位置++it;auto insert_it = lst.insert(it, 99); // 在 it 前插入 99std::cout << "After single insert: ";for (int x : lst) {std::cout << x << " "; // 輸出: 1 99 2 3 4 5}std::cout << "\nInserted element: " << *insert_it << std::endl; // 輸出: 99// 2. 范圍插入(在第三個位置插入數組 {5, 6, 7})int arr[3] = {5, 6, 7};auto range_it = lst.begin();// 手動移動迭代器到第三個位置for(int i = 0; i < 3; ++i){++range_it;}lst.insert(range_it, arr, arr + 3); // 插入數組std::cout << "After range insert: ";for (int x : lst) {std::cout << x << " "; // 輸出: 1 99 2 5 6 7 3 4 5}// 3. 填充插入(在末尾插入 3 個 0)lst.insert(lst.end(), 3, 0); // 末尾插入 3 個 0std::cout << "\nAfter fill insert: ";for (int x : lst) {std::cout << x << " ";// 輸出: 1 99 2 5 6 7 3 4 5 0 0 0}// 1. 單元素刪除(刪除值為 99 的元素)auto delete_it = std::find(lst.begin(), lst.end(), 99); // 查找元素if (delete_it != lst.end()) {auto next_it = lst.erase(delete_it); // 刪除并返回下一個元素的迭代器std::cout << "After single erase: ";for (int x : lst) {std::cout << x << " "; // 輸出: 1 2 5 6 7 3 4 5 0 0 0}std::cout << "\nNext element after erase: " << *next_it << std::endl; // 輸出: 2}// 2. 范圍刪除(刪除從第二個到第四個元素)auto start_it = lst.begin();// 手動移動迭代器到第二個位置for (int i = 0; i < 1 && start_it != lst.end(); ++i, ++start_it);auto end_it = lst.begin();// 手動移動迭代器到第五個位置for (int i = 0; i < 4 && end_it != lst.end(); ++i, ++end_it);lst.erase(start_it, end_it); // 刪除 [start_it, end_it) 范圍內的元素std::cout << "After range erase: ";for (int x : lst) std::cout << x << " "; // 輸出: 1 3 4 5 0 0 0// 3. 邊界條件:刪除 end() 會導致未定義行為// lst.erase(lst.end()); // 錯誤:不能刪除 end()
}
2.5.3 clear、swap函數
void swap(list& other); | 交換當前鏈表與?other ?鏈表的所有元素(包括大小、節點和迭代器有效性) | other :待交換的另一個?std::list ?對象 | 交換后,原鏈表的迭代器指向?other ?的元素,反之亦然; | |||||
void clear(); | 刪除鏈表中的所有元素,釋放所有節點內存 | 所有迭代器/引用失效 (鏈表變為空) |
雖然使用swap函數后,原鏈表的迭代器指向?
other
?的元素,反之亦然,但是開發者不要依賴交換后的迭代器/引用(除非明確知道它們指向另一個鏈表)
以避免潛在的邏輯錯誤和未定義行為
2.5.4 關于find函數
std::list 無find成員函數,調用標準庫中的find函數即可
3.迭代器失效
操作 | 失效的 迭代器/指針/引用類型 | 失效原因 | 避免失效的方法 | |
---|---|---|---|---|
insert | 不失效(插入位置及之前的迭代器、指針、引用 均有效) | std::list ?是雙向鏈表,插入操作僅修改相鄰節點的指針,不移動現有節點,所以不失效 | 無需特殊處理,直接使用插入后的迭代器繼續操作。 | |
erase | 僅失效被刪除節點的迭代器、指針、引用 | erase ?會釋放被刪除節點的內存,導致指向該節點的迭代器/指針/引用失效。 | 刪除前保存下一個節點的迭代器(如? ( | |
clear | 所有迭代器、指針、引用均失效 | clear ?會釋放鏈表中所有節點的內存,導致所有迭代器/指針/引用失效。 | 清空后通過?begin() /end() ?重新獲取迭代器,避免使用舊迭代器。 | |
swap | 所有迭代器、指針、引用失效(除非交換同一鏈表) | 交換后,原鏈表的迭代器指向?other ?的元素,反之亦然。邏輯上所有迭代器失效(內容所屬鏈表已改變)。 | 交換后通過?begin() /end() ?重新獲取迭代器,避免依賴交換后的迭代器。 |