vector 是STL中應用最為廣泛的一類容器,這裡對其重要的特性做一個概括和總結。 vector的初始化
vector的初始化,見如下代碼。
vector<int> v2; // vector with 0 elementvector<int> v3(20); // vector with 20 elements whose value is 0vector<int> v4(20, 5);// vector with 20 elements whose value is 5vector<int> v5{ 20 }; // vector with 1 element whose value is 20vector<int> v6(v4); // copy construct functionvector<int> v7(v4.begin(), v4.end());//construct functionvector<int> v8({ 1,2,3,4,5 });// construct a vector with initialize listvector<int> v9{ 1,2,3,4,5 };// construct a vector with initialize listvector<int> v10 = {1,2,3,4,5};// assignment construct functionvector的容量和大小 vector在記憶體中按照連續方式進行儲存,因此初始化vector時會有一個初始的容量(capacity),容量(capacity)類似於一個電梯的最大容納重量。
向vector中添加資料的時候,如果當前元素個數(size)小於容量(capacity),那麼就會繼續在相應位置插入元素。如果當前元素個數和容量相等,則會對vector的容量進行擴充,一般容量按照當前資料量的2倍方式增長。
reserve可以對vector的容量進行設定,如果即將設定的容量小於當前容量,則vector的容量不會縮小。而如果設定的值大於當前容量,那麼會分配設定的容量。如下代碼:
vector<int> v2;v2.reserve(20);cout << v2.capacity() << endl; // capacity is set to be 20v2.reserve(10);cout << v2.capacity() << endl; // capacity is still 20
resize函數對vector當前元素個數進行大小設定,resize(n),表示將元素個數設定為n個,如果n小於當前size,則會將超過n的元素截斷,只留下n個元素。如果n大於當前size,則將需要添加的元素預設設定為0,如果resize(n,m),則表示將新增元素初始化為m,具體用法如下:
vector<int> values{1,2,3}; // 1 2 3 : size is 3values.resize(5); // 1 2 3 0 0 : size is 5values.resize(7,99); // 1 2 3 0 0 99 99 : size is 7values.resize(6); // 1 2 3 0 0 99 : size is 6
說明:resize(0)並不能將vector中的記憶體釋放,vector的容量不會有任何影響,如果想將vector的capacity設定為0,則有如下辦法: 方法一:clear和shrink_to_fit
vector<int> v2;v2.reserve(20); // capacity is set to be 20v2.clear(); v2.shrink_to_fit(); //clear and shrink_to_fit to set capacity to 0
方法二:resize和shrink_to_fit
vector<int> v2;v2.reserve(20); // capacity is set to be 20v2.resize(0); // resize to be 0 element v2.shrink_to_fit();//resize and shrink_to_fit to set capacity to 0
方法三: swap方法
vector<int> v2;v2.reserve(20); // capacity is set to be 20vector<int> v3; // capacity is 0swap(v2,v3); // v2's capacity is 0
vector的元素個數等於當前容量時,vector中再次增加元素時,vector的容量就會增大,一般按照當前
已有元素的50%進行擴充,當容量太大而不需要時,可以採用shrink_to_fit()來除去多餘的容量以減少記憶體佔用量。
vector訪問元素 vector可以通過方括弧使用索引進行元素訪問,也可以通過at(index)方式訪問,但是
at的訪問效率比方括弧的訪問效率低,這是因為at函數會檢查索引越界問題,而方括弧不會檢查索引是否越界。
成員函數front()和back()函數可以返回vector中第一個和最後一個元素的引用,因為返回的是引用,因而可以進行賦值操作。例如:
vector<int> vec{1,2,3,4};vec.back() = 100; // set last element to 100vec.front() = 10; // set first element to 10 成員函數data()用於返回一個指向數組的指標,它在內部被用來儲存元素。
vector<int> values(10,100);auto pData = values.data();// pData is a pointer point to int*
vector添加元素
注意:向容器中添加元素的唯一方式是使用它的成員函數。如果不調用成員函數,非成員函數既不能添加也不能刪除元素。這意味著容器物件必須通過他所允許的函數去訪問,迭代器是不行的。 增加元素。可以通過使用容器物件的push_back()和emplace_back()函數在序列的末尾添加一個元素。注意:emplace_back比push_back更加有效率。這是因為emplace_back()的參數正是添加到容器中的物件建構函數所需要的參數。emplace_back用它的參數作為建構函式的參數,在容器中產生對象。
vector<string> vec;// 產生一個臨時string對象,再將臨時對象放入vector末尾vec.push_back("hello world1");// 直接當做參數傳遞給末尾string的建構函式,沒有產生臨時對象這一步驟vec.emplace_back("hello world2");string str ("to be or not to be");// emplace_back()中可以直接傳string的建構函式所需要的參數vec.emplace_back(str,0,18);
插入元素。通過成員函數emplace(),可以在vector序列中插入新的元素。對象會在容器中直接產生,而不是先單獨產生對象,然後把它作為參數傳入。emplace()的第一個參數是指定對象的插入位置,後面的參數是構造該對象需要的參數,根據vector中儲存的物件類型不同,其傳入的參數也會不同。
通過成員函數insert()可以在vector中插入一個或者多個元素,第一個參數總是一個指向插入點的const或者non-const迭代器。元素會被迅速插入到第一個參數所指向元素的前面,如果第一個參數是反向迭代器,元素會被插入到迭代器所指向元素的後面。程式碼範例如下。
vector<string> v2;v2.emplace_back("second"); // secondstring str1 = "first"; v2.emplace(v2.begin(), str1); // first second string str2 = "third";v2.emplace(v2.begin() + 1, str2, 0, 5); // first third secondv2.emplace(v2.begin()+1, 4, 'z'); 插入單個元素,insert第二個參數指定插入的值。insert插入單個元素時有兩個重載的版本函數,兩個函數第一個參數都是指定插入位置,第二個參數指定插入元素。第一個版本插入元素類型為const T&,第二個版本的類型是T&&——右值引用。右值引用對象是一個臨時對象,因此插入過程中被移動插入而不是複製插入。注意:使用同樣的參數情況下,調用insert()沒有調用emplace()高效。下述調用insert的函數會產生一個臨時對象作為傳入的第二個參數,但是在emplace()調用中,建構函式用第二個參數直接在容器中產生了字串對象。如下代碼:
vector<string> words {"one","three","eight"};// iter1 point to elment being insertedauto iter1 = words.insert (words.begin()+1,"two")// T&& version,one two three eight,words.emplace(words.begin()+1,"two");// more effective than insert.string str = "nine";// iter2 point to elment being inserted// cosnt T& version,one two three eight nineauto iter2 = words.insert (words.end(),str); 插入元素序列。insert函數可以在某個特定位置前面插入一系列元素。
這是emplace函數所不具有的功能。當插入一系列元素時,insert返回第一個插入的元素的位置。
string more[] = {"five","six","seven"};vector<string> words;words.insert (words.begin(),begin(more),end(more));words.insert (words.end(),{"some", "one", "like", "you"});words.insert (wrods.begin()+1,5,"forward"); // insert 5 "forward"vector刪除元素 使用clear函數將vector中的元素清空,但是capacity並不會釋放。 使用pop_back()可以刪除容器尾部元素。假若要刪除vector中某個位置的元素,可以使用swap和最後一個元素交換,然後使用pop_back()刪除最後一個元素。程式碼範例如下。
vector<int> vec = {1,3,5,7,9};vec.swap(vec.begin()+1,vec.end()-1);vec.pop_back(); // remove 3
成員函數erase可以用來刪除容器中一個或者多個元素,如果只需要刪除一個元素,則提供一個迭代器位置即可,刪除元素後返回刪除元素的下一個位置的迭代器。如果需要刪除一定範圍內的元素,需要提供兩個參數,即刪除範圍的開始和結束位置。
remove()演算法可以刪除指定範圍內匹配特定值的元素。但是remove()是一個全域函數,不能刪除容器中的元素。remove先在vector中尋找要刪除的元素,隨後將該元素後的所有元素前移,以覆蓋該元素,最後將要刪除的元素值設定為預設值。需要注意的是,remove()函數不會改變vector的大小和容量,因此為了刪除多餘的位置,需要配合erase使用。範例程式碼如下:
vector<string> vec = {"one", "none", "some", "all", "none", "most", "many"};auto iter = remove(words.begin(),words.end(),"none");words.erase(iter,words.end());//remove surplus elements