1. 程式人生 > 其它 >侯捷-STL與泛型程式設計筆記(第一講、容器概述——0.概述)

侯捷-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。