STL(Standard Template Library),即標準模板庫,是一個高效的C++程序庫。包含了諸多在計算機科學領域裏經常使用的基本數據結構和基本算法。爲廣大C++程序員們提供了一個可擴展的應用框架,高度體現了軟件的可複用性。其核心思想就是泛化編程(generic programming),在這種思想裏,大部分基本算法被抽象,被泛化,獨立於與之對應的數據結構,用於以相同或相近的方式處理各類不一樣情形。node
STL中包含了6大組件程序員
Containers 經過 Allocators 取得數據存儲空間,Algorithms 經過 Iterators 存取 Containers 內容,Functors 能夠協助 Algorithms 完成不一樣的策略變,Adapters 能夠修飾或套接Containers,Iterators和Functors。算法
容器整體上分爲三大類:編程
是一種固定大小的容器類型,在定義的時候就要聲明大小和類型。Array其實就是對C語言中數組的一種擴充升級,使其支持了迭代器的操做,便於STL算法的使用。array在使用和性能上都要強於內置數組,對於一些固定大小的使用場景,能夠用array來替代原先數組的工做。數組
TR1版本源碼以下:數據結構
template<typename _Tp, std::size_t _Nm> struct array { typedef _Tp value_type; typedef _Tp* pointer; typedef balue_type* iterator; value_type _M_instance[_Nm ? _Nm : 1]; iterator begin() { return iterator(&_M_instance[0]);} iterator end() { return iteratoe(&_M_instance[_Nm]);} ... };
Vector 使用起來和一個數組十分類似,可是在空間用完時,能夠自動擴充本身的空間。通常而言空間的擴充,沒法在原地完成擴充。因此會在內存中新申請一片內存(一般都是以前空間大小的2倍大),而後經過拷貝將原有數據拷貝到新的地址空間。框架
Vector中存在三個指針來代表Vector:dom
須要注意的是:在空間(兩倍)增加的過程當中涉及到了大量的拷貝構造和析構!函數
相較於vector的連續線性空間,List就顯得複雜許多,它的好處是每次插入或刪除一個元素,就配置或釋放一個元素空間。所以,list對於空間的運用有絕對的精準,一點也不浪費。並且,對於任何位置的元素插入或元素移除,List永遠是常數時間。性能
List不只是一個雙向鏈表,並且仍是一個環狀雙向鏈表。 另外,還有一個重要性質,插入操做和接合操做都不會形成原有的List迭代器失效,這在Vector是不成立的。由於Vector的插入操做可能形成空間的從新配置,致使原有的迭代器所有失效。甚至List的元素刪除操做(erase),也只有「指向被刪除元素」的那個迭代器失效,其餘迭代器不受任何影響。
Forward-List容器與List容器的主要設計區別是List保持內部惟一的一個連接到下一個元素,然後者則保持每一個元素的兩個連接:一個指向下一個元素和一個前一個。容許高效在兩個方向迭代,但每一個元素的消耗額外的存儲空間,並輕微較高的時間開銷插入和刪除元素的迭代。Forward-List對象,從而比List對象更有效率,雖然他們只能向前遍歷。
因此Forward-List的一個最大的缺點就是沒法直接訪問指定位置上元素,每次一的訪問都須要從頭開始訪問,這樣的操做須要線型的時間。
能夠向兩端擴充,經過指針鏈接不一樣分段的空間,模擬出連續空間。
template <class T, class Alloc=alloc, size_t BufSiz=0> class deque{ public: typedef T value_type; typedef __deque_iterator<T,T&,T*,BufSiz> iterator; protected: typedef pointer* map_pointer;//T** protected: iterator start; iterator finish; map_pointer map; size_type map_size; public: iterator begin(){return start;} iterator end(){return finish;} size_type size(){return finish-start;} ... }; template <class T, class Ref, class Ptr, size_t BufSiz> struct __deque_iterator{ typedef random_access_iterator_tag iterator_category; typedef T value_type; typedef Ptr pointer; typedef Ref reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T** map_pointer; typedef __deque_iterator self; T* cur; T* first; T* last; map_pointer node; ... };
start指向第一塊分區,finishi指向最後一塊分區,map是用來存放各個分區的地址(vector實現),map_size是map的大小。
start和finish做爲iterator,cur指向當前的元素,first指向第一個存放的元素,last指向當前分區中最後一個存放的數據以後的位置,node指回map。
deque 如何模擬連續空間?
基本所有依靠deque iterators完成
reference operator*() const { return *cur; } pointer operator->() const { return &(operator*()); } difference_type operator-(const self& x) const { return difference_type(buff_size()) * (node - x.node - 1) + (cur - first) + (x.last - x.cur); } self& operator++(){ ++cur; if(cur == last){ set_node(node + 1); cur = first; } return *this; } self operator++(int){ self tmp = *this; ++*this; return tmp; } self& operator--(){ if(cur == first){ set_node(node - 1); cur = last; } --cur; return *this; } self operator--(int){ self tmp = *this; --*this; return tmp; } void set_node(map_pointer new_node){ node = new_node; first = *new_node; last = first + difference_type(buffer_size()); } self& operator+=(difference_type n){ difference_type offset = n + (cur - first); if(offset >= 0 && offset < difference_type(buffer_size())){ cur += n; } else{ difference_type node_offset = offset > 0 ? offset / difference_type(buffer_size()) : -difference_type((-offset - 1) / buffer_size()) - 1; set_node(node + node_offset); cur = first + (offset - node_offset * difference_type(buffer_size())); } return * this; } self operator+(difference_type n) const { self tmp = *thisl return tmp +=n; } self& operator-=(fifference_type n) { return *this += -n; } self operator-(difference_type n) const { self tmp = * this; return tmp -= n; } reference operator[](difference_type n) const { return *(*this + n); }