vector內存增加方式

1、前言ios

    首先說明,vector能夠理解爲動態數組,既然是數組,那麼它在內存中就應該是一塊連續的內存,但vector是如何支持動態增加的呢?關於這個問題,網上有很對說法,但其中有些說法是錯誤的,最近看到有一篇博友的解釋就很是正確vector空間動態增加,這裏就針對的他的解釋進行進一步的闡述,並進行實際驗證。數組

2、vector內存增加方式函數

   C++primer中屢次明確指出對vector使用的建議是:先建立一個空的vector對象,而後再運行時再利用vector的成員函數push_back向其中添加元素。先以此來驗證vector的內存的自動增加,程序說明爲:建立一個空的vector a,而後採用push_back向其中添加元素,共迭代10次,運行環境爲VS2010IDE佈局

  1. #include <iostream>  
  2. #include <vector>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     vector<int> a;  
  7.     cout << "a.size(): " << a.size() << "       a.capacity(): " << a.capacity() << endl;  
  8.     for (int i = 0; i < 10; i++)  
  9.     {  
  10.         a.push_back(i);  
  11.         cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;  
  12.     }  
  13.     return 0;  
  14. }  

運行結果爲:spa

    在分析結果以前,首先介紹與vector的內存佈局,而後再介紹與內存增加相關的四個函數,分別爲size()、capacity()、reserve()、resize()函數。.net

(1)vector內存佈局對象

    start迭代器指向已用空間的首元素,finish指向已用空間的尾元素的下一個位置,end_of_storage指向可用空間的末尾。blog

(2)size()、capacity()、reserve()、resize()函數內存

 

    size()函數返回的是已用空間大小,capacity()返回的是總空間大小,capacity()-size()則是剩餘的可用空間大小。當size()和capacity()相等,說明vector目前的空間已被用完,若是再添加新元素,則會引發vector空間的動態增加。reserve(n)預先分配一塊較大的指定大小的內存空間,其中n爲分配空間大小;resize()成員函數只改變元素的數目,不改變vector的容量。ci

    再看剛剛的運行結果,首先能夠肯定,在VS2010的編譯器裏面每次並非增加固定的內存,能夠看出是增加當前內存的一半。並且因爲咱們的程序沒有調用reserve(n)函數預先分配一塊內存,因此內存增加是編譯器自動完成的。這個自動增加包括從新分配內存空間、拷貝原空間、釋放原空間三個過程,具體策略爲當添加元素時,若是vector空間大小不足,則會以原大小的1.5倍另外配置一塊較大的新空間,而後將原空間內容拷貝過來,在新空間的內容末尾添加元素,並釋放原空間。也就是說vector的空間動態增長大小,並非在原空間以後的相鄰地址增長新空間,由於vector的空間是線性連續分配的,不能保證原空間以後有可供配置的空間。這就解釋了上述程序的運行結果。

    可是,針對以上自動完成的內存增加過程,因爲包括從新分配內存空間、拷貝原空間、釋放原空間等步驟,這些過程會下降程序效率,所以可使用reserve(n)預先分配一塊較大的指定大小的內存空間,這樣當指定大小的內存空間未使用完時,是不會從新分配內存空間的,這樣便提高了效率。下面對上一個程序進行擴展以下,即再定義一個vector b,預先分配10個內存,進行11次push_back操做

  1. #include <iostream>  
  2. #include <vector>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     vector<int> a;  
  7.     cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;  
  8.     for (int i = 0; i < 10; i++)  
  9.     {  
  10.         a.push_back(i);  
  11.         cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;  
  12.     }  
  13.     cout << endl;  
  14.     vector<int> b;  
  15.     b.reserve(10);  
  16.     for (int i = 0; i < 10; i++)  
  17.     {  
  18.         b.push_back(i);  
  19.         cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;  
  20.     }  
  21.     b.push_back(11);  
  22.     cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;  
  23.     cout << endl;  
  24.     return 0;  
  25. }  

運行結果以下:


    能夠看到,在調用了reserve(10)進行預先內存分配以後,前10次push_back操做vector b 的capacity並無增加,可是在第11次push_back操做時,因爲當前b的size() > capacity(),因此vector自動進行了內存擴充,由10變爲15(1.5倍)。也就是說,前10次能避免每次都進行內存擴充,能有效提升效率,可是第11次就不會。但有一點要注意,若是在當前容量沒有用完的狀況下,再一次調用reserve(n)函數時,只有當n > 當前capacity()時,vector當前容量纔會改變。再對上述程序進行擴展,分別加上b.reserve(13)和reserve(20),以下

  1. #include <iostream>  
  2. #include <vector>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     vector<int> a;  
  7.     cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;  
  8.     for (int i = 0; i < 10; i++)  
  9.     {  
  10.         a.push_back(i);  
  11.         cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;  
  12.     }  
  13.     cout << endl;  
  14.     vector<int> b;  
  15.     b.reserve(10);  
  16.     for (int i = 0; i < 10; i++)  
  17.     {  
  18.         b.push_back(i);  
  19.         cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;  
  20.     }  
  21.     b.push_back(11);  
  22.     cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;  
  23.     cout << endl;  
  24.   
  25.   
  26.     b.reserve(13);  
  27.     cout << "after b.reserve(13):" << endl;  
  28.     cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;  
  29.   
  30.   
  31. <span style="white-space:pre;"> </span>b.reserve(20);  
  32.     cout << "after b.reserve(20):" << endl;  
  33.     cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;  
  34.     return 0;  
  35. }  

運行結果爲:

 能夠看到,在加上b.reserve(13),容器b的capacity並無由15變爲13,但加上 b.reserve(20)時卻變化了;這也驗證了上述結論。

   對於resize()成員函數只改變元素的數目,不改變vector的容量的說法能夠從下面的程序進行驗證:

  1. #include <iostream>  
  2. #include <vector>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     vector<int> a;  
  7.     cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;  
  8.     for (int i = 0; i < 10; i++)  
  9.     {  
  10.         a.push_back(i);  
  11.         cout << "a.size(): " << a.size() << "   a.capacity(): " << a.capacity() << endl;  
  12.     }  
  13.     cout << endl;  
  14.     vector<int> b;  
  15.     b.reserve(10);  
  16.     for (int i = 0; i < 10; i++)  
  17.     {  
  18.         b.push_back(i);  
  19.         cout << "b.size(): " << b.size() << "   b.capacity(): " << b.capacity() << endl;  
  20.     }  
  21.     b.push_back(11);  
  22.     cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;  
  23.     cout << endl;  
  24.   
  25.     b.reserve(13);  
  26.     cout << "after b.reserve(13):" << endl;  
  27.     cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;  
  28.   
  29.     b.resize(5);  
  30.     cout << "after b.resize(5):" << endl;  
  31.     cout << "b.size(): " << b.size() << "       b.capacity(): " << b.capacity() << endl;  
  32.   
  33.     for (int i = 0; i < b.size(); i++)  
  34.     {  
  35.         cout << b[i] << endl;  
  36.     }  
  37.     return 0;  
  38. }  

運行結果爲:

能夠看到,在加上resize(5)以後,容器的capacity()並無增加,只是size()變爲了5,並且經過打印vector元素可知,只截取了前五個元素。

相關文章
相關標籤/搜索