vector是c++標準模板庫中的一個容器,簡單來說,vector是一個能夠存放多種類型的動態數組,前提是每個vector只能裝一個類型,說到這裡提一下python的列表和元組,個人認為python的列表要比C++和java的容器好用的多,比如java,從1.5開始支援泛型程式設計,更安全了,但是編譯的時候還是不帶泛型。python中的列表和元組是沒有類型限制的,比如,我在列表中存了一個整形數(python2.5),然後我再存一個字元型也沒有問題,python對列表中的資料類型沒有限制。為什麼python能這麼玩,下篇部落格會專門介紹,python的內建資料類型和用法以及python的一些有趣的bug。
1.vector的資料結構:vector是在記憶體中開闢連續的儲存區,其基本資料結構是順序表,這種資料結構的優點:查詢快,快速定位某個元素的位置,不用挨個遍曆,但是插入慢,因為我在某個位置插入一個元素要移動後面的所有元素的位置,這讓我想到N多老生常談的面試題,比如像java中的ArrayList何LinkedList的區別。其實其本質都是考資料結構的順序表和線性表。
2.vector的屬性:vector之所以稱之為動態數組,要從動態和數組2個角度考慮,所謂動態,就是可以動態擴充,比如vector中有size()方法,返回vector中資料的個數還有capacity()方法,返回此vector的容量,這兩個方法的區別是:就像一個杯子,當前裝了多少水用size(),能裝多少水用capacity()方法:上段代碼,看看vector是怎麼動態追加的:
- //============================================================================
- // Name : test.cpp
- // Author : zhangpeng
- // Version :
- // Copyright : Your copyright notice
- // Description : vector in C++, Ansi-style
- //============================================================================
-
- #include<stdio.h>
- #include<vector>
- using namespace std;
- extern "C"
- typedef vector<int> vec;
-
- int main() {
- vec va;
- va.reserve(20);
- printf("va capacity %d /n",va.capacity());
- printf("va size %d /n",va.size());
- for(int i = 0; i < 30; i++){
- va.push_back(i);
- }
- printf("va capacity %d /n",va.capacity());
- printf("va size %d /n",va.size());
- return 0;
- }
輸出結果是:
va capacity 20
va size 0
va capacity 40
va size 30
這段代碼的意思是:我先設定vector的容量為20(在用reserve()申請緩衝區,這個緩衝區是根據vector內部的動態數組確定大小的),size為0,然後我在va中追加30個元素,然後可以看到,capacity是動態增長的,當vector中的緩衝不夠用的時候,它就會動態把自己的容量擴大1.5到2倍(有些書上說擴大2倍,其實不確切,或者作者沒寫過代碼),當擴大緩衝區的時候,先建立空的緩衝區,然後把值拷貝到新的緩衝區中,這樣的操作讓我想到了hibernate的merge()方法,這樣的操作有弊端,比如我操作大對象,這樣的話效率不高,操作基礎資料型別 (Elementary Data Type)要好些,那我們遇見複雜物件資料類型怎麼辦呢?我們可以操作該對象的指標,就是vector中存指標,這樣效率會明顯提升。
vector中的四個相關成員函數:size() 和capacity()剛才已經介紹過了,現在介紹一下reserve和resize() ,
reserve(n):強制vector把它的容量改為至少n個,如果當前容量大於n,澤vector忽略此操作,如果當前容量小於等於n則vector被強迫重新分配一次,因為他的容量要增加.
resize(n):如果當前大小超出,則銷毀超出部分,如果當前大小小於n,則增加預設值。
3.vector成員函數的其他動作:
c.assign(beg,end) c.assign(n,elem)
將(beg; end)區間中的資料賦值給c。將n個elem的拷貝賦值給c。
c.at(idx) // 建議用這種操作,不要去下標。
傳回索引idx所指的資料,如果idx越界,拋出out_of_range。
c.back()
傳回最後一個資料,不檢查這個資料是否存在。
c.begin()
傳回迭代器中的第一個資料地址。
c.clear()
移除容器中所有資料。
c.empty()
判斷容器是否為空白。
c.end() //指向迭代器中末端元素的下一個,指向一個不存在元素。
c.erase(pos) // 刪除pos位置的資料,傳回下一個資料的位置。
c.erase(beg,end)
刪除[beg,end)區間的資料,傳回下一個資料的位置。
c.front()
傳回第一個資料。
get_allocator
使用建構函式返回一個拷貝。
c.insert(pos,elem) //在pos位置插入一個elem拷貝,傳回新資料位元置
c.insert(pos,n,elem) //在pos位置插入n個elem資料,無傳回值
c.insert(pos,beg,end) //在pos位置插入在[beg,end)區間的資料。無傳回值
c.max_size()
c.~vector<type> 記憶體銷毀
4.vector的迭代器:
vector必須支援迭代功能,說到迭代功能,不得不說下STL種的迭代器。
迭代器中STL中扮演著很重要的角色. STL的核心思想就是:將資料結構和演算法分離。而迭代器就是作為資料結構和演算法的粘合層而存在的。在STL中,每一個容器而有一個自己的迭代器, 而vector的迭代器就是一個普通的指標。所以在vector中實現迭代功能就非常的簡單了。代碼如下:
- vec::iterator iter = va.begin();
- int i = 0;
- while(iter != va.end()){
- printf("va[%d] = %d /n ",i,*iter);
- iter ++;
- i++;
- }
5.回收vector的過剩記憶體:
這樣做的目的是把vector的容量減少到需要的容量:
vector<int>( va).swap(va);
解釋一下:我們先建立一個va的拷貝,vector<int>(va),這是通過vector的拷貝建構函式實現的,是va的一份拷貝,由於使用它的拷貝建構函式只是拷貝元素需要的記憶體,所以這個臨時的va沒有多餘的容量,然後臨時拷貝的va和va進行資料交換,然後臨時的va中有以前沒有用的容量,然後銷毀va的臨時拷貝,回收過剩的記憶體。你可以試一下(vector<int>(va).swap(va)).capacity();
今天就到這,問個問題,我要拿到vector的首地址除了用迭代器還能用其他辦法嗎?