(Boolan) STL與泛型編程第一周筆記

1.源代碼分布

標準庫STL的文件位置,與所采用的編譯器有關:
(1)Visual C++:...\include (例如 D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include)
(2)GNU C++:...\4.9.2\inlcude

2.OOP(Object-Oriented programming) VS GP(Generic programming)

OOP企圖將datas和methods關聯在一起

這里的list不能使用::sort()排序,這是因為::sort()算法設計中的Iterator必須是RandomAccessIterator,而list并不是一個連續空間,在內存中它是由指針一個一個串起來,不能使用指針加法減法。因此list不能使用::sort()排序。

GP卻是將datas和methods分開來,兩者之間通過迭代器聯系在一起。

兩者分開的優點:
(1)Containers和Algorithms團隊可各自閉門造車,其間以Iterator溝通即可;
(2)Algorithms通過Iterators確定操作范圍,并通過Iterators取用Container元素。

補充:
所有的algorithms,最終設計元素本身的操作,無非就是比大小。比如說重新定義max函數,根據字符長度來比大小,我們就必須重寫一個比較函數。


3.源代碼閱讀

基礎:
(1)Operator Overloading 操作符重載
(2)Templates 模板

3.1操作符重載、模板、特化和偏特化
這部分內容在之前額課程中已經講過,不再贅述。

3.2分配器
分配器(Allocator)是容器管理內存的工具,在容器申請內存空間上起作用。
分配器在底層實現上通過operator new()和operator delete()來完成內存分配和釋放,而operator new()和operator delete()實際上是通過調用malloc()和free()函數來實現操作。
operator new()和operator delete()的源代碼如下:


3.2.1 VC6的allocator
VC6所附的標準庫,其allocator實現如下(<xmemory>)



3.2.2 BC5的allocator
BC5所附的標準庫,其allocator實現如下(<memory.stl>)


3.2.3 G2.9的allocator

G2.9所附的標準庫,其allocator實現如下(<defalloc.h>)


3.2.4 G4.9的allocator

G4.9所附的標準庫,其allocator實現如下:


由以上各編譯器中allocator的源代碼可以看出,無論是VC、BC還是GNU的版本中分配器實際上是通過operator new和operator delete來調用malloc和free來管理內存。
但是在GNU2.9中,容器實際使用的并非是allocator,而是alloc,如下圖所示。


alooc的最終實現內存管理也是通過malloc和free,但是可以避免其他額外開銷,比如cookie,實現過程如下:
(1)設計了16條鏈表,每條鏈表負責某種特定大小的區塊,比如第0條鏈表負責8個字節大小的區塊,第1條負責16個字節,以此類推,即(標號數+1)*8;
(2)容器的元素大小都會調整到8的倍數,比如50的會調整到56,然后交給第6條鏈表負責;
(3)分配器查看鏈條有沒有掛內存塊,如果沒有,向操作系統要內存,得到的內存塊除了頭尾有cookie,中間的每一小塊內存都不帶cookie;
實現過程示意圖如下圖所示:

在GNU4.9版本以后,分配器也直接調用了operator new來分配內存,之前2.9中的alloc放入了extention allocators中,也就是__pool_alloc,如下圖所示:


3.3容器的結構與分類
課件里面將容器的結構和分類講得很清楚,具體如下圖所示:


3.4 容器list
3.4.1 list
G2.9的list:



G4.9的list:


3.4.2 list的iterator
G2.9的iterator:


G4.9相較于G2.9:

模板參數只有一個(易理解);
node結構有其parent;
node的成員的type較精確;

具體如下圖所示:

1.C++標準庫和STL
C++標準庫以header files形式呈現:
(1)C++標準庫的header files不帶副檔名(.h),例如#include
(2)新式C header files 不帶副檔名.h,例如#include
(3)舊式C header files (帶有副檔名.h)仍然可用,例如#include
(4)新式headers內的組件封裝于namespace “std”
using namespace std;或者以 using std::cout;的形式
(5)舊式headers 內的組件不封裝于namespace "std"
在標準庫中,標準模板庫STL(Standard Template Library),占據了標準庫70%,80%以上的內容。
STL的核心思想是泛型編程(Generic Programming)。
重要資源:
網站:
http://en.cppreference.com/w/
http://www.cplusplus.com/
https://gcc.gnu.org/
書籍:
The C++ standard Library second edition;
STL 源碼剖析

使用示例:

#include 
#include 
#include 
#include 
using namespace std;
int main()
{
int ia[6] = { 27, 210, 12,47, 109, 83 };
vector> vi(ia, ia + 6);
cout << count_if(vi.begin(), vi.end(),
not1(bind2nd(less(), 40)));
return 0;
}
Paste_Image.png

3.容器的相關知識

3.1容器的結構與分類
容器按在內存中的存儲結構分為三種:順序容器(Sequence Container)、關聯容器(Associative Container)、和無序容器(Unordered Container)。其中的無序容器是C++ 11提出的,實際上無序容器也屬于關聯容器,使用哈希表構成。

Paste_Image.png

3.2順序容器
順序容器:它將單一類型元素聚集起來成為容器,然后根據位置來存儲和訪問這些元素。
標準庫提供了一下幾種順序容器:array、vector、list、forward_list、slist、deque、stack和queue,他們的差別在于訪問元素訪問元素的方式,以及添加或刪除元素相關操作的運行代價。array是C++11的新內容,功能比內置數組更加強大,可以以對象為單位存儲數據,vector支持快速隨機訪問,list支持快速插入/刪除,deque是一個雙端隊列,queue和stack在STL中都是基于deque來實現。

3.2.1順序容器的常用操作
容器定義的操作非常少,只定義了構造函數、添加或刪除元素的操作、設置容器長度的操作以及返回指向特殊元素的迭代器的操作。其他一些有用的操作,如排序、查找,則不是由容器類型定義,而是由標準算法定義。
(1)begin和end成員
begin 和 end 操作產生指向容器內第一個元素和最后一個元素的下一位置的迭代器,這兩個迭代器通常用于標記包含容器中所有元素的迭代器范圍。

Paste_Image.png

(2)添加元素

Paste_Image.png

(3)大小操作

Paste_Image.png

(4)訪問元素

Paste_Image.png

(5)刪除元素

Paste_Image.png

(6)swap交換操作
swap 操作實現交換兩個容器內所有元素的功能。要交換的操作數必須是相同類型的容器,而且所存儲的元素類型也必須相同。調用了 swap 函數后,右操作數原來存儲的元素被存放在左操作數中,反之亦然。 該操作不會刪除或插入任何元素,而且保證在常量時間內實現交換。由于容器內沒有移動任何元素,因此迭代器不會失效。
根據課程舉幾個使用例子:

Paste_Image.png
Paste_Image.png
Paste_Image.png

作者獲得授權,非商業轉載請注明出處。

3.3關聯容器
在STL中關聯容器使用紅黑樹來實現,因為不是順序結構,因而不能使用上面提到的push和pop函數,使用insert和erase函數來實現元素的插入刪除操作。
關聯容器支持通過鍵來高效地查找和讀取元素,兩個基本的關聯容器類型是map和set。map的元素以鍵-值(key-value)對的形式組織:鍵用于元素在map中的索引,而值則表示所存儲和讀取的數據。set僅包含一個鍵,并有效地支持關于某個鍵是否存在的查詢。map可理解為字典,set可理解為一類元素的集合。
關聯容器和順序容器的本質差別在于:關聯容器通過鍵(key)存儲和讀取元素,而順序容器則通過元素在容器中的位置順序存儲和訪問元素。
et 和 map 類型的對象所包含的元素都具有不同的鍵,不允許為同一個鍵添加第二個元素。如果一個鍵必須對應多個實例,則需使用 multimap 或 multi set,這兩種類型允許多個元素擁有相同的鍵。
根據課程舉幾個例子:

Paste_Image.png

3.4無序容器
嚴格意義上講,無序容器也屬于關聯容器。

Paste_Image.png
Paste_Image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容