C++ STL vector容量(capacity)和大小(size)的區別


很多初學者分不清楚 vector 容器的容量(capacity)和大小(size)之間的區別,甚至有人認為它們表達的是一個意思。本節將對 vector 容量和大小各自的含義做一個詳細的介紹。

vector 容器的容量(用 capacity 表示),指的是在不分配更多內存的情況下,容器可以保存的最多元素個數;而 vector 容器的大小(用 size 表示),指的是它實際所包含的元素個數。

對於一個 vector 對象來說,通過該模板類提供的 capacity() 成員函數,可以獲得當前容器的容量;通過 size() 成員函數,可以獲得容器當前的大小。例如:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main()
  5. {
  6. std::vector<int>value{ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 };
  7. value.reserve(20);
  8. cout << "value 容量是:" << value.capacity() << endl;
  9. cout << "value 大小是:" << value.size() << endl;
  10. return 0;
  11. }

程序輸出結果為:

value 容量是:20
value 大小是:15

結合該程序的輸出結果,圖 1 可以更好的說明 vector 容器容量和大小之間的關系。



圖 1 vector 容量和大小的區別


顯然,vector 容器的大小不能超出它的容量,在大小等於容量的基礎上,只要增加一個元素,就必須分配更多的內存。注意,這里的“更多”並不是 1 個。換句話說,當 vector 容器的大小和容量相等時,如果再向其添加(或者插入)一個元素,vector 往往會申請多個存儲空間,而不僅僅只申請 1 個。

一旦 vector 容器的內存被重新分配,則和 vector 容器中元素相關的所有引用、指針以及迭代器,都可能會失效,最穩妥的方法就是重新生成。

舉個例子:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main()
  5. {
  6. vector<int>value{ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 };
  7. cout << "value 容量是:" << value.capacity() << endl;
  8. cout << "value 大小是:" << value.size() << endl;
  9. printf("value首地址:%p\n", value.data());
  10. value.push_back(53);
  11. cout << "value 容量是(2):" << value.capacity() << endl;
  12. cout << "value 大小是(2):" << value.size() << endl;
  13. printf("value首地址: %p", value.data());
  14. return 0;
  15. }

運行結果為:

value 容量是:15
value 大小是:15
value首地址:01254D40
value 容量是(2):22
value 大小是(2):16
value首地址: 01254E80

可以看到,向“已滿”的 vector 容器再添加一個元素,整個 value 容器的存儲位置發生了改變,同時 vector 會一次性申請多個存儲空間(具體多少,取決於底層算法的實現)。這樣做的好處是,可以很大程度上減少 vector 申請空間的次數,當后續再添加元素時,就可以節省申請空間耗費的時間。

因此,對於 vector 容器而言,當增加新的元素時,有可能很快完成(即直接存在預留空間中);也有可能會慢一些(擴容之后再放新元素)。

修改vector容器的容量和大小

另外,通過前面的學習我們知道,可以調用 reserve() 成員函數來增加容器的容量(但並不會改變存儲元素的個數);而通過調用成員函數 resize() 可以改變容器的大小,並且該函數也可能會導致 vector 容器容量的增加。比如說:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main()
  5. {
  6. vector<int>value{ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 };
  7. cout << "value 容量是:" << value.capacity() << endl;
  8. cout << "value 大小是:" << value.size() << endl;
  9. value.reserve(20);
  10. cout << "value 容量是(2):" << value.capacity() << endl;
  11. cout << "value 大小是(2):" << value.size() << endl;
  12. //將元素個數改變為 21 個,所以會增加 6 個默認初始化的元素
  13. value.resize(21);
  14. //將元素個數改變為 21 個,新增加的 6 個元素默認值為 99。
  15. //value.resize(21,99);
  16. //當需要減小容器的大小時,會移除多余的元素。
  17. //value.resize(20);
  18. cout << "value 容量是(3):" << value.capacity() << endl;
  19. cout << "value 大小是(3):" << value.size() << endl;
  20. return 0;
  21. }

運行結果為:

value 容量是:15
value 大小是:15
value 容量是(2):20
value 大小是(2):15
value 容量是(3):30
value 大小是(3):21

程序中給出了關於 resize() 成員函數的 3 種不同的用法,有興趣的讀者可自行查看不同用法的運行結果。

可以看到,僅通過 reserve() 成員函數增加 value 容器的容量,其大小並沒有改變;但通過 resize() 成員函數改變 value 容器的大小,它的容量可能會發生改變。另外需要注意的是,通過 resize() 成員函數減少容器的大小(多余的元素會直接被刪除),不會影響容器的容量。

vector容器容量和大小的數據類型

在實際場景中,我們可能需要將容器的容量和大小保存在變量中,要知道 vector<T> 對象的容量和大小類型都是 vector<T>::size_type 類型。因此,當定義一個變量去保存這些值時,可以如下所示:

  1. vector<int>::size_type cap = value.capacity();
  2. vector<int>::size_type size = value.size();

size_type 類型是定義在由 vector 類模板生成的 vecotr 類中的,它表示的真實類型和操作系統有關,在 32 位架構下普遍表示的是 unsigned int 類型,而在 64 位架構下普通表示 unsigned long 類型。

當然,我們還可以使用 auto 關鍵字代替 vector<int>::size_type,比如:

  1. auto cap = value.capacity();
  2. auto size = value.size();


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM