vector是c++標準模板庫中的一個容器,簡單來說,vector是一個能夠存放多種類型的動態(tài)數(shù)組,前提是每個vector只能裝一個類型,說到這里提一下python的列表和元組,個人認為python的列表要比C++和java的容器好用的多,比如java,從1.5開始支持泛型編程,更安全了,但是編譯的時候還是不帶泛型。python中的列表和元組是沒有類型限制的,比如,我在列表中存了一個整形數(shù)(python2.5),然后我再存一個字符型也沒有問題,python對列表中的數(shù)據(jù)類型沒有限制。為什么python能這么玩,下篇博客會專門介紹,python的內置數(shù)據(jù)類型和用法以及python的一些有趣的bug。
1.vector的數(shù)據(jù)結構:vector是在內存中開辟連續(xù)的存儲區(qū),其基本數(shù)據(jù)結構是順序表,這種數(shù)據(jù)結構的優(yōu)點:查詢快,快速定位某個元素的位置,不用挨個遍歷,但是插入慢,因為我在某個位置插入一個元素要移動后面的所有元素的位置,這讓我想到N多老生常談的面試題,比如像java中的ArrayList何LinkedList的區(qū)別。其實其本質都是考數(shù)據(jù)結構的順序表和線性表。
2.vector的屬性:vector之所以稱之為動態(tài)數(shù)組,要從動態(tài)和數(shù)組2個角度考慮,所謂動態(tài),就是可以動態(tài)擴展,比如vector中有size()方法,返回vector中數(shù)據(jù)的個數(shù)還有capacity()方法,返回此vector的容量,這兩個方法的區(qū)別是:就像一個杯子,當前裝了多少水用size(),能裝多少水用capacity()方法:上段代碼,看看vector是怎么動態(tài)追加的:
-
-
-
-
-
-
-
-
- #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()申請緩存區(qū),這個緩存區(qū)是根據(jù)vector內部的動態(tài)數(shù)組確定大小的),size為0,然后我在va中追加30個元素,然后可以看到,capacity是動態(tài)增長的,當vector中的緩存不夠用的時候,它就會動態(tài)的把自己的容量擴大1.5到2倍(有些書上說擴大2倍,其實不確切,或者作者沒寫過代碼),當擴大緩存區(qū)的時候,先創(chuàng)建空的緩存區(qū),然后把值拷貝到新的緩存區(qū)中,這樣的操作讓我想到了hibernate的merge()方法,這樣的操作有弊端,比如我操作大對象,這樣的話效率不高,操作基本數(shù)據(jù)類型要好些,那我們遇見復雜對象數(shù)據(jù)類型怎么辦呢?我們可以操作該對象的指針,就是vector中存指針,這樣效率會明顯提升。
vector中的四個相關成員函數(shù):size() 和capacity()剛才已經介紹過了,現(xiàn)在介紹一下reserve和resize() ,
reserve(n):強制vector把它的容量改為至少n個,如果當前容量大于n,澤vector忽略此操作,如果當前容量小于等于n則vector被強迫重新分配一次,因為他的容量要增加.
resize(n):如果當前大小超出,則銷毀超出部分,如果當前大小小于n,則增加默認值。
3.vector成員函數(shù)的其他操作:
c.assign(beg,end) c.assign(n,elem)
將(beg; end)區(qū)間中的數(shù)據(jù)賦值給c。將n個elem的拷貝賦值給c。
c.at(idx) // 建議用這種操作,不要去下標。
傳回索引idx所指的數(shù)據(jù),如果idx越界,拋出out_of_range。
c.back()
傳回最后一個數(shù)據(jù),不檢查這個數(shù)據(jù)是否存在。
c.begin()
傳回迭代器中的第一個數(shù)據(jù)地址。
c.clear()
移除容器中所有數(shù)據(jù)。
c.empty()
判斷容器是否為空。
c.end() //指向迭代器中末端元素的下一個,指向一個不存在元素。
c.erase(pos) // 刪除pos位置的數(shù)據(jù),傳回下一個數(shù)據(jù)的位置。
c.erase(beg,end)
刪除[beg,end)區(qū)間的數(shù)據(jù),傳回下一個數(shù)據(jù)的位置。
c.front()
傳回第一個數(shù)據(jù)。
get_allocator
使用構造函數(shù)返回一個拷貝。
c.insert(pos,elem) //在pos位置插入一個elem拷貝,傳回新數(shù)據(jù)位置
c.insert(pos,n,elem) //在pos位置插入n個elem數(shù)據(jù),無返回值
c.insert(pos,beg,end) //在pos位置插入在[beg,end)區(qū)間的數(shù)據(jù)。無返回值
c.max_size()
c.~vector<type> 內存銷毀
4.vector的迭代器:
vector必須支持迭代功能,說到迭代功能,不得不說下STL種的迭代器。
迭代器中STL中扮演著很重要的角色. STL的核心思想就是:將數(shù)據(jù)結構和算法分離。而迭代器就是作為數(shù)據(jù)結構和算法的粘合層而存在的。在STL中,每一個容器而有一個自己的迭代器, 而vector的迭代器就是一個普通的指針。所以在vector中實現(xiàn)迭代功能就非常的簡單了。代碼如下:
- 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的拷貝構造函數(shù)實現(xiàn)的,是va的一份拷貝,由于使用它的拷貝構造函數(shù)只是拷貝元素需要的內存,所以這個臨時的va沒有多余的容量,然后臨時拷貝的va和va進行數(shù)據(jù)交換,然后臨時的va中有以前沒有用的容量,然后銷毀va的臨時拷貝,回收過剩的內存。你可以試一下(vector<int>(va).swap(va)).capacity();
今天就到這,問個問題,我要拿到vector的首地址除了用迭代器還能用其他辦法嗎?