1.底層實現原理
-
vector的底層資料結構比較簡單,時一段連續的儲存空間,即陣列。
//_Alloc 表示記憶體分配器,此引數幾乎不需要我們關心 template <class _Ty, class _Alloc = allocator<_Ty>> class vector{ ... protected: pointer _Myfirst; pointer _Mylast; pointer _Myend; };
從它的原始碼中可以看出,它是通過三個指標來實現的。
- _Myfirst 指向的是 vector 容器物件的起始位元組位置;
- _Mylast 指向當前最後一個元素的末尾位元組;
- _Myend 指向整個 vector 容器所佔用記憶體空間的末尾位元組。
通過這三個指標來完成各種功能,下面舉幾個例子說明,詳細說明在API函式中會進行講解。
- iterator begin() {return _Myfirst;}
- iterator end() {return _Mylast;}
- size_type size() const {return size_type(end() - begin());}
- size_type capacity() const {return size_type(_Myend - begin());}
- bool empty() const {return begin() == end();}
- reference operator[] (size_type n) {return *(begin() + n);}
- reference front() { return *begin();}
- reference back() {return *(end()-1);}
注意:當vector為空時,三個指標都為null!
-
vector的擴容
vector是自動擴容的,當插入的資料大於當前vector的容量時,不同編譯器的擴容是不一樣的,VS本身就會自動擴大容量50%。
擴容過程如下所示:- 找到一塊新的地址空間,申請連續空間。
- 將舊空間中的資料按順序移動到新地址空間中。
- 釋放掉舊空間中的記憶體。
2.常用的API函式
函式名 | 功能 |
---|---|
empty(); | 判斷vector是否為空 |
capacity(); | 容器的容量 |
size(); | 容器資料的數量(大小) |
push_back(elem); | 在尾部插入一個元素 |
pop_back(elem); | 刪除尾部的一個元素 |
assign(beg, end); | 區間中的資料拷貝賦值給本身 |
assign(n,elem); | 將n個elem拷貝賦值給本身 |
insert(const_iterator pos, (count),elem); | 在pos位置插入(count)個elem元素 |
erase(const_iterator pos); | 刪除指定位置的元素 |
clear(); | 清空所有位置的元素 |
reserve(int len); | 設定vector的容量 |
at(int idx); | 根據索引取值 |
operator[]; | 返回索引idx所指的資料 |
front(); | 返回容器中第一個資料元素 |
back(); | 返回容器中最後一個資料元素 |
另外c++11對push_back()進行了改進,提供了emplace_back()函式。
它們的區別主要在於是否進行了深度拷貝或者移動建構函式。
-
push_back(Person)
- 首先建立Person物件。
- 把Person複製到vector的尾部元素(拷貝/移動構造)。若是深拷貝,那麼會影響效能,佔用更多的堆空間。
- 若是拷貝需要銷燬掉之前建立好的物件。
-
emplace_back(Person)
直接在vector的尾部新建物件。
程式碼實現如下所示。void* ptr = malloc(sizeof(Person)); new (ptr)Person();
第1行: 主要是分配一個Person物件所需的記憶體空間, 但在vector裡, 這步不需要考慮, 內部會在實現;
第2行: 這才是重點, 通過這樣的語法, 就可以對已在的記憶體空間, 呼叫相應的Person類建構函式進行初始化;
同理emplace與insert也是一樣的道理
3.迭代器失效解決辦法
- reserve()函式對vector進行擴容時,會造成迭代器失效。
- erase()函式刪除元素時,返回值就是下一個迭代器,在迴圈時容易造成迭代器丟失。
4.參考文獻
vector底層實現機制
vector的函式使用
push_back()和emplace_back()詳解
移動建構函式詳解