1.C++標準庫和STL C++標準庫以header files形式呈現: (1)C++標準庫的header files不帶尾碼名(.h),例如#include (2)新式C header files 不帶尾碼名.h,例如#include (3)舊式C header files (帶有尾碼名.h)仍... ...
1.C++標準庫和STL
C++標準庫以header files形式呈現:
(1)C++標準庫的header files不帶尾碼名(.h),例如#include <vector>
(2)新式C header files 不帶尾碼名.h,例如#include<cstdio>
(3)舊式C header files (帶有尾碼名.h)仍然可用,例如#include <stdio.h>
(4)新式headers內的組件封裝於namespace “std”
using namespace std;或者以 using std::cout;的形式
(5)舊式headers 內的組件不封裝於namespace "std"
在標準庫中,標準模板庫STL(Standard Template Library),占據了標準庫70%,80%以上的內容。
C++ 標準庫的範圍大於STL的範圍。
STL的核心思想是泛型編程(Generic Programming)。
重要資源:
網站:
書籍:
- The C++ standard Library second edition;
- STL 源碼剖析
2.STL 六大部件
#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); cout << count_if(vi.begin(), vi.end(), not1(bind2nd(less<int>(), 40))); return 0; }
上述這段代碼用到了STL的六大部件:
allocator 是分配器,vector 是容器,count_if 是演算法
vi.begin() 是迭代器
not1,bind2nd是適配器
less<int> 是仿函數
- 理解容器的前閉後開的設計。迭代器類似於指針,很多操作和指針差不多++,--運算。vec.begin(),vec.end()指向容器最後一個元素的下一個位置,解引用*(vec.end())錯誤!
- auto關鍵字的應用
3.容器的相關知識
3.1容器的結構與分類
容器按在記憶體中的存儲結構分為三種:順序容器(Sequence Container)、關聯容器(Associative Container)、和無序容器(Unordered Container)。其中的無序容器是C++ 11提出的,實際上無序容器也屬於關聯容器,使用哈希表構成。
- Array數組容器,大小固定的
- Deque:兩段都可以進行插入刪除操作,但是從記憶體上講不通,怎麼實現的要從後面的學習知道。
- List:是一個雙向的迴圈鏈表,註意是雙向的。
- Forward-List:單向鏈表,當能用單向鏈表的時候儘量用,可以減少記憶體空間,一個指針在32位pc上占4個位元組,當數據量很多上百萬,不可忽略!
- Set鍵值都一樣,MultiSet允許元素有重覆。
- Set/Map用紅黑樹實現,RB-tree是自平衡的二叉樹。
- Unorder Containers:是C++標準庫里賣的內容。
- 根據這些圖例,可以知道這些容器在記憶體用到的數據結構是什麼樣的。
- HashTable實現方法很多,但基本都用Separate Chaining(分離鏈地址法實現)。
3.2順序容器
順序容器:它將單一類型元素聚集起來成為容器,然後根據位置來存儲和訪問這些元素。
標準庫提供了一下幾種順序容器:array、vector、list、forward_list、slist、deque、stack和queue,他們的差別在於訪問元素訪問元素的方式,以及添加或刪除元素相關操作的運行代價。array是C++11的新內容,功能比內置數組更加強大,可以以對象為單位存儲數據,vector支持快速隨機訪問,list支持快速插入/刪除,deque是一個雙端隊列,queue和stack在STL中都是基於deque來實現。
順序容器類型
vector
可變大小數組;
支持快速隨機訪問;
在尾部之外的位置插入或刪除元素可能很慢;
deque
雙端隊列;
支持快速隨機訪問;
在頭尾位置插入/刪除速度很快;
list
雙向鏈表;
只支持雙向順序訪問;
在list中任何位置進行插入/刪除操作速度都很快;
forward_list
單向鏈表;
只支持單向順序訪問;
在鏈表任何位置進行插入/刪除操作速度都很快;
array
固定大小數組;
支持快速隨機訪問;
不能添加或刪除元素;
string
與vector相似的容器,但專門用於保存字元;
隨機訪問快;
在尾部插入/刪除速度快;
array 測試代碼
#include <array> #include <iostream> #include <ctime> #include <cstdlib> //qsort, bsearch, NULL namespace jj01 { void test_array() { cout << "\ntest_array().......... \n"; array<long, ASIZE> c; clock_t timeStart = clock(); for (long i = 0; i< ASIZE; ++i) { c[i] = rand(); } cout << "milli-seconds : " << (clock() - timeStart) << endl; // cout << "array.size()= " << c.size() << endl; cout << "array.front()= " << c.front() << endl; cout << "array.back()= " << c.back() << endl; cout << "array.data()= " << c.data() << endl; long target = get_a_target_long(); timeStart = clock(); ::qsort(c.data(), ASIZE, sizeof(long), compareLongs); long* pItem = (long*)::bsearch(&target, (c.data()), ASIZE, sizeof(long), compareLongs); cout << "qsort()+bsearch(), milli-seconds : " << (clock() - timeStart) << endl; // if (pItem != NULL) cout << "found, " << *pItem << endl; else cout << "not found! " << endl; } }
3.3關聯容器
在STL中關聯容器使用紅黑樹來實現,因為不是順序結構,因而不能使用上面提到的push和pop函數,使用insert和erase函數來實現元素的插入刪除操作。
關聯容器支持通過鍵來高效地查找和讀取元素,兩個基本的關聯容器類型是map和set。map的元素以鍵-值(key-value)對的形式組織:鍵用於元素在map中的索引,而值則表示所存儲和讀取的數據。set僅包含一個鍵,並有效地支持關於某個鍵是否存在的查詢。map可理解為字典,set可理解為一類元素的集合。
關聯容器和順序容器的本質差別在於:關聯容器通過鍵(key)存儲和讀取元素,而順序容器則通過元素在容器中的位置順序存儲和訪問元素。
et 和 map 類型的對象所包含的元素都具有不同的鍵,不允許為同一個鍵添加第二個元素。如果一個鍵必須對應多個實例,則需使用 multimap 或 multi set,這兩種類型允許多個元素擁有相同的鍵。
3.4無序容器
嚴格意義上講,無序容器也屬於關聯容器。