程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ STL學習之二:容器vector大總結

C++ STL學習之二:容器vector大總結

編輯:C++入門知識




一、容器vector

使用vector必須包含頭文件<vector>:

#include<vector>

型別vector是一個定義於namespace std內的template:


[cpp]
template<class _Ty, 
    class _Ax = allocator<_Ty> > 
template<class _Ty,
 class _Ax = allocator<_Ty> >第二個參數定義內存模型。我們一般采用默認的內存模型。

 


二、vector的功能

vector模塑出一個動態數組。vector將其元復制到內部的動態數組中。元素之間總是存在某種順序,它是一種有序群集。支持隨即存取。它的迭代器是隨機存取迭代器,所以對任何一個STL算法都奏效。

向vector添加一個元素或者刪除其中的一個元素,其後的所有元素都要移動位置,每一次移動都要調用賦值操作符。所以,在末端添加或刪除元素,性能很好。但是在前段或者中部的話,性能較差。

vector優異性能的秘訣之一是它配置比其所容納的元素所需更多的內存。我們需要了解大小和容量的關系。

函數size()可以返回vector的大小,即vector中實際元素的個數。

而capacity()返回容量,是當前的vector所實際能夠容納的元素的數量。它應該總是大於或者等於vector的大小。如果需要向vector中放置比capacity更多的元素,則需要重新配置內部存儲器。vector的容量也會隨之增長。看下面的示例代碼:


[cpp]
#include <iostream>  
#include <vector>  
#include <string>  
#include <algorithm>  
using namespace std; 
 
int main() 

    vector<string> sentence(1); 
    cout << "max_size():" << sentence.max_size() << endl; 
    cout << "size():" << sentence.size() << endl; 
    cout << "capacity():" << sentence.capacity() << endl; 
 
    sentence.reserve(5); 
 
    sentence.push_back("Hello,"); 
    sentence.push_back("how "); 
    sentence.push_back("are "); 
    sentence.push_back("you "); 
    sentence.push_back("?"); 
 
    copy(sentence.begin(),sentence.end(), 
        ostream_iterator<string>(cout," ")); 
    cout << endl; 
 
    cout << "max_size():" << sentence.max_size() << endl; 
    cout << "size():" << sentence.size() << endl; 
    cout << "capacity():" << sentence.capacity() << endl; 
 
    swap(sentence[1],sentence[3]); 
 
    sentence.insert(find(sentence.begin(),sentence.end(),"?"), 
        "always"); 
 
    sentence.back() = "!"; 
 
    copy(sentence.begin(),sentence.end(), 
        ostream_iterator<string>(cout," ")); 
 
    cout << endl; 
 
    cout << "max_size():" << sentence.max_size() << endl; 
    cout << "size():" << sentence.size() << endl; 
    cout << "capacity():" << sentence.capacity() << endl; 

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
 vector<string> sentence(1);
 cout << "max_size():" << sentence.max_size() << endl;
 cout << "size():" << sentence.size() << endl;
 cout << "capacity():" << sentence.capacity() << endl;

 sentence.reserve(5);

 sentence.push_back("Hello,");
 sentence.push_back("how ");
 sentence.push_back("are ");
 sentence.push_back("you ");
 sentence.push_back("?");

 copy(sentence.begin(),sentence.end(),
  ostream_iterator<string>(cout," "));
 cout << endl;

 cout << "max_size():" << sentence.max_size() << endl;
 cout << "size():" << sentence.size() << endl;
 cout << "capacity():" << sentence.capacity() << endl;

 swap(sentence[1],sentence[3]);

 sentence.insert(find(sentence.begin(),sentence.end(),"?"),
  "always");

 sentence.back() = "!";

 copy(sentence.begin(),sentence.end(),
  ostream_iterator<string>(cout," "));

 cout << endl;

 cout << "max_size():" << sentence.max_size() << endl;
 cout << "size():" << sentence.size() << endl;
 cout << "capacity():" << sentence.capacity() << endl;
}運行結果:
\

 

在程序中,當再次向vector插入元素時,由於vector的容量不夠,所以引起了內存的重新分配。但是capacity()的結果與實作版本有關,max_size也是。

 


vector的容量十分重要,是因為:

1、一旦內存重新配置,與之相關的所有的reference、pointers、iterators都會失效。

2、內存配置很費時。

解決這個問題的方法有:

1、可以使用reserve()保留適當容量,減少重新配置內存的次數。示例代碼:


[cpp]
vector<string> sentence(1); 
sentence.reserve(50); 
vector<string> sentence(1);
sentence.reserve(50);2、在初始化期間向構造函數傳遞附加參數,構造出足夠的空間。
[cpp]
vector<T> v(5); 
vector<T> v(5);當然,這種元素的型別必須提供默認構造函數。但是如果元素的型別比較復雜,初始化操作也很耗時。如果只是為了保留足夠的內存,使用方法1較好。

注意:reserve不能縮減vector的容量。由此,我們可以知道,即使刪除元素,其reference、pointers、iterators也會繼續有效,指向動作發生前的位置。

但是插入操作可能使reference、pointers、iterators失效(因為可能會導致重新配置空間)。

 


使用swap函數可以縮減vector容量。因為兩個vector交換內容後,他們的容量也會互換。

1、


[cpp]
template<class T> 
void shrinkCapacity(vector<T> &v) 

    vector<T> tmp(v); 
    v.swap(tmp); 

template<class T>
void shrinkCapacity(vector<T> &v)
{
 vector<T> tmp(v);
 v.swap(tmp);
}2、
[cpp]
vector<T>(v).swap(v); 
vector<T>(v).swap(v);上面兩種方法等價。 www.2cto.com
都是先構造出一個臨時vector對象,以v的元素進行初始化,再與v進行交換。需要注意的是:臨時對象一般都是精確分配實際所需的內存。所以能夠起到減小vector容量的效果。

 


三、vector的操作函數

所有的構造函數和析構函數如下:

 \


 

非變動性操作:

 \


 

賦值操作:

 \


 

上述操作進行的是將新元素賦值給vector,並將舊元素全部移除!示例代碼:


[cpp]
#include <iostream>  
#include <vector>  
#include <string>  
#include <algorithm>  
using namespace std; 
 
int main() 

    vector<string> sentence(1); 
    cout << "max_size():" << sentence.max_size() << endl; 
    cout << "size():" << sentence.size() << endl; 
    cout << "capacity():" << sentence.capacity() << endl; 
 
    sentence.reserve(5); 
 
    sentence.push_back("Hello,"); 
    sentence.push_back("how "); 
    sentence.push_back("are "); 
    sentence.push_back("you "); 
    sentence.push_back("?"); 
 
    copy(sentence.begin(),sentence.end(), 
        ostream_iterator<string>(cout," ")); 
    cout << endl; 
 
    sentence.assign(3,"new"); 
 
    copy(sentence.begin(),sentence.end(), 
        ostream_iterator<string>(cout," ")); 
    cout << endl; 

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
 vector<string> sentence(1);
 cout << "max_size():" << sentence.max_size() << endl;
 cout << "size():" << sentence.size() << endl;
 cout << "capacity():" << sentence.capacity() << endl;

 sentence.reserve(5);

 sentence.push_back("Hello,");
 sentence.push_back("how ");
 sentence.push_back("are ");
 sentence.push_back("you ");
 sentence.push_back("?");

 copy(sentence.begin(),sentence.end(),
  ostream_iterator<string>(cout," "));
 cout << endl;

 sentence.assign(3,"new");

 copy(sentence.begin(),sentence.end(),
  ostream_iterator<string>(cout," "));
 cout << endl;
}運行結果:
\


 

可以看出原來的元素全部被刪除了。


元素存取

 \


 

在這幾個函數中,唯一進行下標檢查的是at函數。

因此,在調用operator[]的時候,必須心理清楚索引是否是有效的。

 


迭代器相關函數

 \


 

迭代器失效的兩種情況是:

1、在一個較小的位置上刪除或者是移動元素。

2、由於容量的變換引起內存重新分配。

 


插入和移除元素

 \


 

插入和移除元素,都會使“作用點”之後的各元素的reference、pointers、iterators失效。插入操作還可能引發內存重新分配,那麼該容器上的所有的reference、pointers、iterators都會失效。

 


四、把vector當做一般數組使用

現在的C++標准保證vector的元素必須分布於連續空間中。對於vector中的一個合法索引,滿足下列表達式:

&v[i] = &v[0] + i;

我們必須保證vector能夠容納所有數據。如果使用的是C-String,記住最後有個'\0'。

只要我們需要一個元素型別為T的數組,就可以采用vector<T>,然後傳遞第一個元素的地址給它。

注意:千萬不要把迭代器當做第一元素的地址來傳遞。因為vector迭代器是由實作版本定義的,不一定是一個一般指針。


[cpp]
printf("%s",v.begin());//ERROR(might work,but not portable)  
printf("%s",&v[0]);//OK 
printf("%s",v.begin());//ERROR(might work,but not portable)
printf("%s",&v[0]);//OK



摘自  江南煙雨

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved