目錄
1.? 語法格式
2.? 說明
3.? 用法示例
1.? 語法格式
??? 描述控制可變長度元素序列的對象。該序列存儲為單向(前向)鏈接的節點列表,每個節點包含一個 Type 類型的成員。
template <class Type,
??? class Allocator = allocator<Type>>
??? class forward_list;
Type:要存儲在 forward_list 中的元素數據類型。
Allocator:存儲的分配器對象,封裝了有關 forward_list 內存分配和釋放的詳細信息。此參數為可選參數。默認值為 allocator<Type>。
2.? 說明
??? forward_list 對象通過基于 allocator 類(通常稱為 std::allocator)的 Allocator 類存儲對象為其控制的序列分配和釋放存儲空間。allocator 對象必須具有與 allocator 類型對象相同的外部接口。
??? 當迭代器、指針和引用所控制的序列中的元素通過 forward_list 刪除時,它們可能會失效。通過 forward_list 對受控序列執行插入和拼接操作不會使迭代器失效。
??? 受控序列的添加可以通過調用 forward_list::insert_after 來實現,該函數是唯一一個調用構造函數 Type(const T&) 的成員函數。forward_list 也可能調用移動構造函數。如果此類表達式引發異常,則容器對象不會插入任何新元素并重新引發異常。因此,當發生此類異常時,forward_list 類型的對象處于已知狀態。
??? 分配容器對象時,不會復制存儲的分配器對象。
??? forward_list 容器和雙向鏈表容器list的主要設計區別在于,前者在內部只保留指向下一個元素的鏈接,而后者每一個元素保留兩個鏈接:一個指向下一個元素,一個指向前一個元素,從而允許雙向高效迭代,但每個元素會消耗額外的存儲空間,并且插入和刪除元素的時間開銷略高。因此,forward_list 對象比列表對象更高效,盡管它們只能向前迭代。對于存儲零個或少數幾個元素的場景非常合適。
??? 與其他基本標準序列容器(數組、向量和雙端隊列)相比,forward_list 在容器內任何位置插入、提取和移動元素方面通常表現更佳,因此在大量使用這些元素的算法(例如排序算法)中也表現出色。
??? 與其他序列容器相比,forward_list 和列表的主要缺點在于它們無法通過元素的位置直接訪問元素;例如,要訪問 forward_list 中的第六個元素,必須從起始位置迭代(即遍歷)到該位置,這需要線性時間。它們還會消耗一些額外的內存來保存與每個元素關聯的鏈接信息(這對于包含小元素的大型列表來說可能是一個重要因素)。
??? forward_list 類模板在設計時就考慮到了效率:從設計上講,它與簡單的手寫 C 語言單鏈表一樣高效,事實上,它是唯一一個出于效率考慮而故意省略 size 成員函數的標準容器:由于其鏈表性質,如果 size 成員函數的執行時間是常量級的,則需要維護一個內部計數器來記錄其大小(就像雙向list一樣)。這會消耗一些額外的存儲空間,并使插入和刪除操作的效率略有降低。要獲取 forward_list 對象的大小,可以使用距離算法及其 begin 和 end 函數,這是一個線性時間操作。
3.? 用法示例
// forward_list_splice_after.cpp
// compile with: /EHsc /W4
#include <forward_list>
#include <iostream>
using namespace std;
template <typename S> void print(const S& s) {
??? for (const auto& p : s) {
??????? cout << "(" << p << ") ";
??? }
??? cout << endl;
}
int main()
{
??? forward_list<int> c1{ 10, 11 };
??? forward_list<int> c2{ 20, 21, 22 };
??? forward_list<int> c3{ 30, 31 };
??? forward_list<int> c4{ 40, 41, 42, 43 };
??? forward_list<int>::iterator where_iter;
??? forward_list<int>::iterator first_iter;
??? forward_list<int>::iterator last_iter;
??? cout << "Beginning state of lists:" << endl;
??? cout << "c1 = ";
??? print(c1);
??? cout << "c2 = ";
??? print(c2);
??? cout << "c3 = ";
??? print(c3);
??? cout << "c4 = ";
??? print(c4);
??? where_iter = c2.begin();
??? ++where_iter; // start at second element
??? c2.splice_after(where_iter, c1);
??? cout << "After splicing c1 into c2:" << endl;
??? cout << "c1 = ";
??? print(c1);
??? cout << "c2 = ";
??? print(c2);
??? first_iter = c3.begin();
??? c2.splice_after(where_iter, c3, first_iter);
??? cout << "After splicing the first element of c3 into c2:" << endl;
??? cout << "c3 = ";
??? print(c3);
??? cout << "c2 = ";
??? print(c2);
??? first_iter = c4.begin();
??? last_iter = c4.end();
??? // set up to get the middle elements
??? ++first_iter;
??? c2.splice_after(where_iter, c4, first_iter, last_iter);
??? cout << "After splicing a range of c4 into c2:" << endl;
??? cout << "c4 = ";
??? print(c4);
??? cout << "c2 = ";
??? print(c2);
}
輸出:
Beginning state of lists:c1 = (10) (11)c2 = (20) (21) (22)c3 = (30) (31)c4 = (40) (41) (42) (43)After splicing c1 into c2:c1 =c2 = (20) (21) (10) (11) (22)After splicing the first element of c3 into c2:c3 = (30)c2 = (20) (21) (31) (10) (11) (22)After splicing a range of c4 into c2:c4 = (40) (41)c2 = (20) (21) (42) (43) (31) (10) (11) (22)