1. 程式人生 > >STL Vector 常用操作整理(比較全面易懂的整理)

STL Vector 常用操作整理(比較全面易懂的整理)

用法:前半部分是基礎的常用操作,後邊是參考來得完整的介紹

 1.檔案包含:     

        #include<vector>

          using namespace std;

  2.宣告向量:

               2.1  一維陣列,例:vector <int> a;(等於聲明瞭一個int陣列a[],大小沒有指定,可以動態的向裡面新增刪除)。

               2.2  二維陣列,例:vector <int *> a;

  3.常用成員函式:其中vector<int>  v.

v[i];   返回第i個元素


v.size();  返回容量,陣列真是長度

v.push_back(elem);  v的結尾加入元素elem

v.pop_back();   刪除v的最後一個元素

v.insert(pos,elem);    在pos位置插入elem元素  ps:pos要是迭代器 pos = v.begin()

v.earse(pos);      刪除pos位置的元素

v.empty();       判斷是否為空

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

比較全面的介紹:

3. 初始化   
vector                 // 建立一個空的vector。
vector c1(c2)          // 複製一個vector
vector c(n)            // 建立一個vector,含有n個數據,資料均已預設構造產生
vector c(n, elem)      // 建立一個含有n個elem拷貝的vector
vector c(beg,end)      // 建立一個含有n個elem拷貝的vector


4. 解構函式
c.~vector ()           // 銷燬所有資料,釋放記憶體


5. 成員函式
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.capacity()  // 返回容器中資料個數。
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.pop_back()       // 刪除最後一個數據。
c.push_back(elem)  // 在尾部加入一個數據。
c.rbegin()         // 傳回一個逆向佇列的第一個資料。
c.rend()           // 傳回一個逆向佇列的最後一個數據的下一個位置。
c.resize(num)      // 重新指定佇列的長度。
c.reserve()        // 保留適當的容量。
c.size()           // 返回容器中實際資料的個數。
c1.swap(c2)
swap(c1,c2)        // 將c1和c2元素互換。同上操作。

operator[]         // 返回容器中指定位置的一個引用。



               4.記憶體管理與效率

      1》使用reserve()函式提前設定容量大小,避免多次容量擴充操作導致效率低下。

        關於STL容器,最令人稱讚的特性之一就是是隻要不超過它們的最大大小,它們就可以自動增長到足以容納你放進去的資料。(要知道這個最大值,只要呼叫名叫max_size的成員函式。)對於vector和string,如果需要更多空間,就以類似realloc的思想來增長大小。vector容器支援隨機訪問,因此為了提高效率,它內部使用動態陣列的方式實現的。在通過 reserve() 來申請特定大小的時候總是按指數邊界來增大其內部緩衝區。當進行insert或push_back等增加元素的操作時,如果此時動態陣列的記憶體不夠用,就要動態的重新分配當前大小的1.5~2倍的新記憶體區,再把原陣列的內容複製過去。所以,在一般情況下,其訪問速度同一般陣列,只有在重新分配發生時,其效能才會下降。正如上面的程式碼告訴你的那樣。而進行pop_back操作時,capacity並不會因為vector容器裡的元素減少而有所下降,還會維持操作之前的大小。對於vector容器來說,如果有大量的資料需要進行push_back,應當使用reserve()函式提前設定其容量大小,否則會出現許多次容量擴充操作,導致效率低下。

      reserve成員函式允許你最小化必須進行的重新分配的次數,因而可以避免真分配的開銷和迭代器/指標/引用失效。但在我解釋reserve為什麼可以那麼做之前,讓我簡要介紹有時候令人困惑的四個相關成員函式。在標準容器中,只有vector和string提供了所有這些函式。

(1) size()告訴你容器中有多少元素。它沒有告訴你容器為它容納的元素分配了多少記憶體。
(2) capacity()告訴你容器在它已經分配的記憶體中可以容納多少元素。那是容器在那塊記憶體中總共可以容納多少元素,而不是還可以容納多少元素。如果你想知道一個vector或string中有多少沒有被佔用的記憶體,你必須從capacity()中減去size()。如果size和capacity返回同樣的值,容器中就沒有剩餘空間了,而下一次插入(通過insert或push_back等)會引發上面的重新分配步驟。
(3) resize(Container::size_type n)強制把容器改為容納n個元素。呼叫resize之後,size將會返回n。如果n小於當前大小,容器尾部的元素會被銷燬。如果n大於當前大小,新預設構造的元素會新增到容器尾部。如果n大於當前容量,在元素加入之前會發生重新分配。
(4) reserve(Container::size_type n)強制容器把它的容量改為至少n,提供的n不小於當前大小。這一般強迫進行一次重新分配,因為容量需要增加。(如果n小於當前容量,vector忽略它,這個呼叫什麼都不做,string可能把它的容量減少為size()和n中大的數,但string的大小沒有改變。在我的經驗中,使用reserve來從一個string中修整多餘容量一般不如使用“交換技巧”,那是條款17的主題。)

     這個簡介表示了只要有元素需要插入而且容器的容量不足時就會發生重新分配(包括它們維護的原始記憶體分配和回收,物件的拷貝和析構和迭代器、指標和引用的失效)。所以,避免重新分配的關鍵是使用reserve儘快把容器的容量設定為足夠大,最好在容器被構造之後立刻進行。

例如,假定你想建立一個容納1-1000值的vector<int>。沒有使用reserve,你可以像這樣來做:

vector<int> v;
for (int i = 1; i <= 1000; ++i) v.push_back(i);
在大多數STL實現中,這段程式碼在迴圈過程中將會導致2到10次重新分配。(10這個數沒什麼奇怪的。記住vector在重新分配發生時一般把容量翻倍,而1000約等於210。)

把程式碼改為使用reserve,我們得到這個:

vector<int> v;
v.reserve(1000);
for (int i = 1; i <= 1000; ++i) v.push_back(i);
這在迴圈中不會發生重新分配。

在大小和容量之間的關係讓我們可以預言什麼時候插入將引起vector或string執行重新分配,而且,可以預言什麼時候插入會使指向容器中的迭代器、指標和引用失效。例如,給出這段程式碼,

string s;
...
if (s.size() < s.capacity()) {
s.push_back('x');
}
push_back的呼叫不會使指向這個string中的迭代器、指標或引用失效,因為string的容量保證大於它的大小。如果不是執行push_back,程式碼在string的任意位置進行一個insert,我們仍然可以保證在插入期間沒有發生重新分配,但是,與伴隨string插入時迭代器失效的一般規則一致,所有從插入位置到string結尾的迭代器/指標/引用將失效。

回到本條款的主旨,通常有兩情況使用reserve來避免不必要的重新分配。第一個可用的情況是當你確切或者大約知道有多少元素將最後出現在容器中。那樣的話,就像上面的vector程式碼,你只是提前reserve適當數量的空間。第二種情況是保留你可能需要的最大的空間,然後,一旦你新增完全部資料,修整掉任何多餘的容量。

       2》使用“交換技巧”來修整vector過剩空間/記憶體

      有一種方法來把它從曾經最大的容量減少到它現在需要的容量。這樣減少容量的方法常常被稱為“收縮到合適(shrink to fit)”。該方法只需一條語句:vector<int>(ivec).swap(ivec);
表示式vector<int>(ivec)建立一個臨時vector,它是ivec的一份拷貝:vector的拷貝建構函式做了這個工作。但是,vector的拷貝建構函式只分配拷貝的元素需要的記憶體,所以這個臨時vector沒有多餘的容量。然後我們讓臨時vector和ivec交換資料,這時我們完成了,ivec只有臨時變數的修整過的容量,而這個臨時變數則持有了曾經在ivec中的沒用到的過剩容量。在這裡(這個語句結尾),臨時vector被銷燬,因此釋放了以前ivec使用的記憶體,收縮到合適。

     3》用swap方法強行釋放STL Vector所佔記憶體

template < class T> void ClearVector( vector<T>& v )
{
    vector<T>vtTemp;
    vtTemp.swap( v );
}

    vector<int> v ;
    nums.push_back(1);
    nums.push_back(3);
    nums.push_back(2);
    nums.push_back(4);
    vector<int>().swap(v);

/* 或者v.swap(vector<int>()); */

/*或者{ std::vector<int> tmp = v;   v.swap(tmp);   }; //加大括號{ }是讓tmp退出{ }時自動析構*/

5.Vector 記憶體管理成員函式的行為測試

       C++ STL的vector使用非常廣泛,但是對其記憶體的管理模型一直有多種猜測,下面用例項程式碼測試來了解其記憶體管理方式,測試程式碼如下:

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

int main()
{
vector<int> iVec;
cout << "容器 大小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //1個元素, 容器容量為1

iVec.push_back(1);
cout << "容器 大小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //2個元素, 容器容量為2

iVec.push_back(2);
cout << "容器 大小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //3個元素, 容器容量為4

iVec.push_back(3);
cout << "容器 大小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //4個元素, 容器容量為4

iVec.push_back(4);
iVec.push_back(5);
cout << "容器 大小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //5個元素, 容器容量為8

iVec.push_back(6);
cout << "容器 大小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //6個元素, 容器容量為8

iVec.push_back(7);
cout << "容器 大小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //7個元素, 容器容量為8

iVec.push_back(8);
cout << "容器 大小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //8個元素, 容器容量為8

iVec.push_back(9);
cout << "容器 大小為: " << iVec.size() << endl;
cout << "容器 容量為: " << iVec.capacity() << endl; //9個元素, 容器容量為16
/* vs2005/8 容量增長不是翻倍的,如
    9個元素   容量9
    10個元素 容量13 */

/* 測試effective stl中的特殊的交換 swap() */
cout << "當前vector 的大小為: " << iVec.size() << endl;
cout << "當前vector 的容量為: " << iVec.capacity() << endl;
vector<int>(iVec).swap(iVec);

cout << "臨時的vector<int>物件 的大小為: " << (vector<int>(iVec)).size() << endl;
cout << "臨時的vector<int>物件 的容量為: " << (vector<int>(iVec)).capacity() << endl;
cout << "交換後,當前vector 的大小為: " << iVec.size() << endl;
cout << "交換後,當前vector 的容量為: " << iVec.capacity() << endl;

return 0;
}

6.vector的其他成員函式

        c.assign(beg,end):將[beg; end)區間中的資料賦值給c。
        c.assign(n,elem):將n個elem的拷貝賦值給c。
        c.at(idx):傳回索引idx所指的資料,如果idx越界,丟擲out_of_range。
        c.back():傳回最後一個數據,不檢查這個資料是否存在。
        c.front():傳回地一個數據。
        get_allocator:使用建構函式返回一個拷貝。
        c.rbegin():傳回一個逆向佇列的第一個資料。
        c.rend():傳回一個逆向佇列的最後一個數據的下一個位置。
        c.~ vector <Elem>():銷燬所有資料,釋放記憶體。   

7.備註:在用vector的過程中的一些問題,特此列出討論:

               1)

                    vector <int > a;

                    int  b = 5;

                    a.push_back(b);

                    此時若對b另外賦值時不會影響a[0]的值

                2)

vector <int*> a;
                     int *b;
                     b= new int[4];
                     b[0]=0;
                     b[1]=1;
                     b[2]=2;
                     a.push_back(b);
                     delete b;          //釋放b的地址空間
                     for(int i=0 ; i <3 ; i++)
                     {
                           cout<<a[0][i]<<endl;
                     }

                     此時輸出的值並不是一開始b陣列初始化的值,而是一些無法預計的值.

                    分析:根據1) 2)的結果,可以想到,在1)中,  往a向量中壓入的是b的值,即a[0]=b,此時a[0]和b是儲存在兩個不同的地址中的.因此改變b的值不會影響a[0];而在2)中,因為是把一個地址(指標)壓入向量a,即a[0]=b,因此釋放了b的地址也就釋放了a[0]的地址,因此a[0]陣列中存放的數值也就不得而知了.  

相關推薦

STL Vector 常用操作整理(比較全面易懂整理)

用法:前半部分是基礎的常用操作,後邊是參考來得完整的介紹  1.檔案包含:              #include<vector>           using namespace std;   2.宣告向量:                2.1 

STL map常用操作簡介

iterator 完成後 clas str typedef size_type 它的 stl map [] 1。目錄 map簡介 map的功能 使用map 在map中插入元素 查找並獲取map中的元素 從map中刪除元素 2。map簡介 map是一類

如何在VC中加減日期及 CTime COleDateTime的常用操作比較

如何在VC中加減日期 使用CTime類,如:    CTime t1( 1999, 3, 19, 22, 15, 0 ); // 10:15PM March 19, 1999    CTime t2( 1999, 3, 20, 22, 15, 0 ); // 10:15PM March 20, 1999  

vector常用操作

resize 與reserve的區別    reserve是容器預留空間,但並不真正建立元素物件,在建立物件之前,不能引用容器內的元素,因此當加入新的元素時,需要用push_back()/insert()函式。    resize是改變容器的大小,並且建立物件,因此,呼叫這個函式之後,就可以引用容器內的物件了

pandas與data.table比較常用操作整理

在對資料表進行日常操作時,有一些操作是經常用到的,記錄如下: 1.輸入:從檔案讀取資料/從頭建立一個dataframe pd.DataFrame(data,index=[list],columns=[list]) 2.修改列名、索引列 a.columns = [your list her

.Net Standard HttpClient封裝Htt請求常用操作整理

return AD eth ive ada encoding web ray lencod 一、常用Http操作 1.Get請求,有參數,無參數 2.Post 請求,有參數,無參數 3.文件簡單下載 /// <summary> /// http

SQL 語句常用操作整理

新增新使用者建議 GRANT 命令 一、grant 普通資料使用者,查詢、插入、更新、刪除 資料庫中所有表資料的權利。 grant select on testdb.* to [email protected]'%' grant insert on testdb.* to [ema

Visio2010常用操作備忘整理

1.線條、矩形的擦除鍵   檔案——選項——快速訪問工具欄——刪除——確定,之後在新建選項卡里找到刪除鍵 2.箭頭畫法   開始——線條 3.改變箭頭指向    檢視——任務管理——大小和位置,該角度引數 4. Visio2007和

vector物件的初始化和常用操作

使用vector需要包含標頭檔案vector。 1、初始化vector物件的方法 1)vector<T> v1; // v1是一個空vector,它潛在的元素是T型別的,執行預設初始化。2)vector<T> v2(v1); // v2中包含有v1所有元素的副本。3)vector&

Hbase常用操作整理(持續更新)

1. 查詢操作 HBase中rowkey可以唯一標識一行記錄,在HBase查詢的時候,有以下幾種方式: 通過get方式,指定rowkey獲取唯一一條記錄 通過scan方式,設定startRow和stopRow引數進行範圍匹配 全表掃描,即直接掃描整張表中所有行

STL基礎4:STL7個常用容器的比較

1.STL容器分類: STL的容器可以分為以下幾個大類:  一 順序(序列)容器, 有vector, list, deque, string,stack( 介面卡類), queue( 介面卡類), priority queues( 介面卡類) 二   關聯容器,     有

Linux vim編輯器常用操作技巧整理

經常發現一些作者寫書或寫文章喜歡被使用者挾持,內容搞的大而全,鬍子眉毛一把抓,最後導致結果讀者還是不滿意。 其實,只要能說清楚一個知識點,能幫助新手劃定技術點的知識邊界就是很好的文章了!本文講解的是vim編輯器常用操作技巧整理,讀者如果能熟練掌握這些常見的技巧,就可以給運維和開發工作帶來非常大的便利

STL vector用法介紹+ STL 常用函式用法

1 #include <iostream> 2 #include <deque> 3 4 using namespace std; 5 6 int main() 7 { 8 deque<int> d; 9 10 //尾部插入 11

C++STL裡面7個常用容器的比較

1.STL容器分類: STL的容器可以分為以下幾個大類:  一 順序(序列)容器, 有vector, list, deque, string,stack( 介面卡類), queue( 介面卡類), priority queues( 介面卡類) 二   關聯容器,     有set, multiset,

STL常用vector,map,set,sort 用法

1. push_back()   在陣列的最後新增一個數據 2. pop_back()    去掉陣列的最後一個數據 3. at()               得到編號位置的資料 4. begin()           得到陣列頭的指標 5. end()             得

C++中陣列與STLvector和array的比較

我的Github個人部落格 ----------------------------------- 阮一峰的網路日誌 ----------------------------------- 劉未鵬 | Mind Hacks ---------------------------

STL常用vector,map,set,sort 用法

STL中的常用的vector,map,set,sort,pair用法 C++的標準模板庫(Standard Template Library,簡稱STL)是一個容器和演算法的類庫。容器往往包

STLvector常用方法 二維vectorvector陣列指標

一.使用包含 #include <vector> using namespace std; 二.宣告 1、一維陣列: vector<int> a; vector<int> a(100, 0); //宣告長

Vim常用操作整理備份

游標移動等基本命令 1.上下左右移動游標:     h:左    l:右    k:上    j:下 2.刪除一行:dd 3.刪除一個字元:x 4.刪除一個換行符:J 5.在游標下方新建一行,並且進入插入模式:o(小寫字母o) 6.在游標上方新建一行,並且進入插入模式:O(大寫字母O) 7.游標移動到下一

shell指令碼中字串常用操作整理

shell中常用字串操作整理 shell指令碼中常用字串操作如下: 1. 字串的比較 2. 字串的長度 3. 擷取字串 4. 字串的替換 下面分別講解這些操作的用法。 1. 字串的比較 1.1. 等於和不等於 user=zabbix # 這是最常用的 if [