STL之vector的使用

2021-05-24 11:09:12 字數 3810 閱讀 9074

本文**

vector是連續記憶體容器,換句話說,標準要求所有標準庫實現的時候,vector中的元素的記憶體必須是連續的。所以對於插入和刪除的時間複雜度是很高的,因為刪除或者插入的時候,需要元素的移動,即元素複製拷貝。

vector的內部實現一般需要用到placement new ,所以效率很高,因為很多的時候,只要我們是使用得到,就可以省去很多的記憶體分配開銷。而且vector的使用,元素可以沒有預設的建構函式,但是需要拷貝建構函式的存在,這是使用carray所無法實現的。

使用原則:

1,盡量使用vector代替c風格的陣列或者carray;

2,盡量使用演算法代替手工寫的迴圈;

3,盡量使用vector本身的函式代替其他泛型演算法;

vector的介面很容易看懂和使用,這裡以一些例子來說明vector的用法。

1,填充vector

如果我們想用原始陣列的內容填充vector,那麼於有很多種方式。我們來一次學習vector的幾個方法。

例如我們有陣列int v1[10] = ;

初始化方式1:

vectorv2(10); //初始化size為10可以避免陣列動態增長的時候不斷的分配記憶體

//v2.reserve(10);//同上,只要使用其中乙個就可以了

for( int i=0; i<10; i++ )

初始化方式2:

vectorv3(&v1[0],&v1[9]);//原始陣列的元素指標可以作為迭代器來使用

初始化方式3:

vectorv4;

v4.reserve(10);

v4.insert(v4.begin(), &v1[0], &v[9]);

初始化方式4:

vectorv5(10);

copy(v5.begin(), &v1[0], &v1[9]);

原始陣列的元素指標可以作為迭代器來使用。

原則:盡量使用reserve來減少不必要的記憶體分配次數。

原則:盡量使用empty而不是size()==0 來判斷容器是否為空

有可能我們需要在vector中插入相應的元素

vector::iterator i = find( v1.begin(), v1.end(), 3);

if( i != v1.end() )

2,遍歷vector

例如有vectorv1;

void print( int i)

方式1:

for( int i=0; i

這種方式是我們最熟悉的,但是不夠好,寫起來不夠簡潔。而且對於沒有隨機迭代器的其他容器來說,這樣做是辦不到的。

方式2:

typedef vector:: iterator   vintiterator;

vintiterator end = v1.begin();

for( vintiterator i=v1.begin(); i != end; ++i )

注意:先計算end有好處,因為不必要每次去重複計算end,vector的end()不是常數時間的,所以先快取下來能提高效率。寫演算法的時候盡量使用!=比較迭代器,因為《對於很多非隨機迭代器沒有這個操作符。

但是這種方式也寫起來比較繁瑣。

方式3:

for_each( v1.begin(), v1.end(), print );

使用演算法寫起來簡單多了。

使用演算法的時候,可以使用函式物件,例如

class output

} for_each( v1.begin(), v1.end(), output );

3,vector中的刪除

刪除指定元素

vectorv1;

//….初始化**

vector:: iterator i = find( v1.begin(), v1.end(), 3.0 );

if( i != v1.end() )

這樣就真的刪除了麼指定的元素了麼?沒有。其實只是內部的元素作了移動,vector的刪除的時間複雜度是很高的。所以選擇容器的時候,如果需要頻繁在中間插入和刪除元素,那選擇vector就會影響效率了。

注意:插入或者刪除操作會使得迭代器失效。

原則:使用erase-remove慣用法刪除元素

v1.erase( remove(v1.begin(), v1.end(), 3.0), v1.end() );

4,vector是否為空

在判斷容器是否為空的時候,使用empty()來代替size()是否為了0的檢查方式,因為empty更加高效時間複雜度是常數時間的,size()時間複雜度不是常數時間的。

原則:使用empty判斷標準容器是否為空

5,vector中的查詢

原則:盡量使用標準容器自帶的演算法代替公共演算法。

但是vector中並沒有多少自己的演算法,倒是list中有remove ,remove_if,sort,reverse等演算法。

find

find_if

6,使用交換技巧來修正過剩的容量

vectorv1;

//…初始化v1

//…刪除v1中所有的元素

但是這個時候v1的記憶體容量並不是0,還是很大的一塊記憶體沒有釋放,如果想清空

用v1.reserve(0);到不到目標,因為reserve只能擴大記憶體容量,並不能減小。

vectorv2;

v2.swap(v1);

這個時候就是真的將之記憶體容量降到最低了。

6,題外話:使用演算法及其他技巧

原則:不要使用auto_ptr作為模板引數來建立容器,這會產生意想不到的陷阱,因為auto_ptr的拷貝有特殊的語義

原則:避免使用vector, 因為它不能當作標準容器來用

copy

find_if

for_each

原則:盡量使用區間成員函式代替它們的單元素引數兄弟成員函式

區間構造

區間刪除

區間賦值

區間插入

原則:使得容器中元素的拷貝操作輕量而正確,拷貝是stl中容器的執行的基本方式,將元素加入到容器,必然保持乙個拷貝,容器中的元素不再是原來的那個元素,所以如果將指標加入容器,必須在容器離開作用域以前刪除指標所指的物件。

void fun()

}

原則:注意對於 vector,任何插入刪除操作都會引起迭代器失效。所以要小心。

第二部分 使用錯誤討論

vector的語義常被誤解,所以經常會出現使用錯誤

1,案例一

你能發現下面的問題所在麼?

void func( vector<.int>& v1 )

#1和#2有何區別?

void func1( vector& v1 )

cout << v1[0];

v1.reserve(100);

assert(v1.capicity() == 100 );

cout << v1[0];

v1[2] = 3;

v1[3] = 4;

//……

v[99] = 100;

for( vector::iterator i = v1.begin(); i

} 函式func1存在什麼問題(叢風格和**正確性做出評價)?會列印出什麼?

2,案例二

使用vector的時候最容易發生的執行時錯誤,莫過於迭代器錯誤

注意:對於 vector,任何插入刪除操作都會引起迭代器失效。所以要小心

STL之vector使用詳解

好久不用stl了,忘的差不多了,總結一下vector的使用方式,就不對每個方法做出詳細解釋了,只給出了如何用 void testvector 構造乙個元素值全為2大小為10的vector vectorv1 10,2 用指標構造 vectorv2 a,a 10 用vector iterator構造 v...

STL之使用vector排序

應用場景 在記憶體中維持乙個有序的vector 1 2 3 include 4 include 5 include 67 先自定義乙個結構體 8struct test 13bool sortbym1 const test v1,const test v2 注意 本函式的引數的型別一定要與vector...

教你使用STL容器之vector

c 語言本身提供了乙個序列式容器array,stl另外再提供vector list deque stack queue priority queue等序列式容器。vector的資料安排以及操作方式,與array是很相似的,唯一的不同點在於空間的運用的靈活性,array是靜態的,一旦配置了就不能再改變...