侯捷-STL與泛型程式設計筆記(第一講、容器概述——0.概述)
參考:連結
一、簡介
C++標準庫的header files不帶.h字尾的,如:#include
這種形式的head files稱為新式headers,新式headers內元件封裝在namespace “std”(新式統一規定都在std)
using namespace std;(全部載入)
using std::cout;(cout單個)
常用網站:
- CPlusPlus.com
- CppReference.com
- gcc.gnu.org
我最常使用的是CPlusPlus.com。使用方法就是在搜尋框中搜索想要的查詢的類。千萬不要認為這種開發手冊就很複雜,而且是英文的,就不去看。你去認真去看了就會發現,開發手冊寫得很好。因為我英語不好,所以在搜尋函式的後,會直接看開發手冊給的例項,比如我在搜尋vector的insert函式的使用時,會直接看手冊中的程式碼例項,然後可能會去看看英文的講解或者直接去百度了。
我認為本視訊應該需要配套《stl原始碼剖析(侯捷)》看。
二、STL六大部件(components)
容器(Containers):容器儲存資料
分配器(Allocators):分配器為容器分配記憶體
演算法(Algorithms):演算法處理容器的資料
迭代器(Iterators):迭代器為演算法提供訪問容器的方式
介面卡(Adapters):進行轉換,具體如何轉換,以後介紹
仿函式(Functors):仿函式為類似不同的類相加減提供支援。(???我還是不懂仿函式是什麼?)
六大部件的關係:
2.1.一個例子說明六大部件
//一個例子說明六大部件 #include <vector> #include <algorithm> #include <functional> #include <iostream> using namespace std; int main() { int ia[6] = {27, 210, 12, 47, 109, 83}; vector<int, allocator<int>> vi(ia,ia + 6);//<>符號表示模板,allocator<int>是一個分配器模板。 // 如果將本行程式碼改為vector<int>,則vector會使用預設的分配器 cout << count_if(vi.begin(), vi.end(), not1(bind2nd(less<int>(), 40))); // 輸出大於等於四十的數的個數 return 0; } //vector是一個容器containers //count_if是一個演算法algorithm,計算vi裡符合條件的元素個數 //vi.begin(), vi.end()是一個迭代器iterator。 //vi.begin()指向第一個元素,vi.end()指向最後一個元素的下一個元素 //less<int>是一個仿函式function //bind2nd是一個介面卡function adapter,它將40繫結到less函式的第二個形參上 //notl是一個介面卡function adapter,表示否定。bind2nd(less<int>(), 40)的結果相當於 //{true,false,true,false,false,false},則not1(bind2nd(less<int>(), 40))就相當於{false,true,false,true,true,true}
我現在暫時對泛性程式設計的理解是:演算法獨立與資料結構,也就說函式count_if不止可以用於操作vector型別的資料,還可以操作其他型別的資料,如這個中的例子
2.2.遍歷容器中所有元素
舊版遍歷: Container<T> c; ... Container<T>::iterator ite = c.begin(); for (; ite != c.end(); ++ite) ... C++11遍歷: for (decl:coll){ // 其中coll為容器或者陣列 statement } //舉例如下: //1. for (int i: {2,3,4,5,6,7,8,9,10}) { std::cout << i << std::endl; } //2. int ia[] = {2,3,4,5,6,7,8,9,10} for (int i: ia) { std::cout << i << std::endl; } //3. std::vector<double> vec; ... for (auto elem : vec) { // auto代表讓編譯器判斷,這裡應該是個什麼型別 std::cout << elem << std::endl; // 不需要進行解引用操作 } for (auto& elem : vec) { // auto&使得對elem的修改,就相當於對vec中相應元素的修改 elem *= 3; }
2.3.容器種類
順序容器Sequence Containers
- Array(固定元素個數)C++11:就是我們平時使用的陣列,不過把現在用一個類將它包裝起來。陣列元素的個數在定義的時候就已經確定,不可擴充。
- Vector(尾部個數可以擴充)
- Deque(頭尾個數可以擴充)
- List(雙向連結串列)
- Forward-List(單向連結串列)C++11
關聯容器Associative Container(通過key可以找到value):關聯容器一般使用紅黑樹進行實現。查詢速度快,但由於插入的時候需要調整紅黑樹而導致插入速度慢。
- Set/Multiset(key=value):multiset允許重複元素,Set不允許有重複。
- Map/Multimap(key對應value;multimap允許重複元素,map不允許有重複。
不定序容器Unordered Containers(屬於關聯容器):使用hash表進行實現。包括unordered_map、unordered_multimap、unordered_set、unordered_multiset,具體使用,請參考cplusplus.com
各個容器的結構:
介面卡(看作一種不能使用迭代器的容器):
有三種介面卡:佇列(queue)、優先佇列( priority queue)和棧(stack),
介面卡不允許使用迭代器iterator,因為這會破壞棧和佇列訪問元素的特性(先進後出和先進先出)。
接下來侯捷老師講解了幾種容器的使用,可以直接參考我的寫的部落格,或者直接在開發手冊中進行學習
allocator:在第一章的allocator,啥也沒有介紹。
問題
1.map的重複元素指的是key重複嗎??
答:是的,指的就是key不可以重複
2.如果map或set插入相同key的value時,不會報錯。map插入相同key的value時,會將key對應的value改成新插入的value。
3.mutimap不可以使用[]來做插入??
答:應該是因為multimap允許插入重複元素的原因,所以就不可以使用[]來做插入
4.為什麼侯捷將容器介面卡stack和queue也當成容器來說明??
答:stack和queue的內部使用的deque進行實現的。由於這兩種容器沒有自己的資料結構,它們是借用deque進行實現的,所以在技術上,有些人將stack和queue稱為Container Adapter。