C++primer第九章 順序容器 9.4 vector對象是如何增長的

  • 為了支持快速隨機訪問,vector將元素連續存儲,每個元素緊挨著前一個元素存儲。通常情況下,我們不必關心一個標準庫類型是如何實現的,而只需關心它如何使用。然而,對于vector和string,其部分實現滲透到了接口中。
  • 假定容器中元素是連續存儲的,且容器的大小是可變的,考慮向vector或string中添加元素會發生什么:如果沒有空間容納新元素,容器不可能簡單地將它添加到內存中其他位置--因為元素必須連續存儲。容器必須分配新的內存空間來保存已有元素和新元素,已有元素從舊位置移動到新空間中,然后添加新元素,釋放舊存儲空間。如果我們每添加一個新元素,vector就執行一次這樣的內存分配和釋放操作,性能會慢到不可接受。為了避免這種代價,標準庫實現者采用了可以減少容器空間重新分配次數的策略。當不得不獲取新的內存空間時,vector和string的實現通常會分配比新的空間需求更大的內存空間。容器預留這些空間作為備用,可用來保存更多的新元素(提前分配更大的空間)。這樣,就不需要每次添加新元素都重新分配容器的內存空間了。這種分配策略比每次添加新元素時都重新分配容器內存空間的策略要高效得多。其實際性能也表現得足夠好--雖然vector在每次重新分配內存空間時都要移動所有元素,但使用此策略后,其擴張操作通常比list和deque還要快。

管理容量的成員函數

  • 如表9.10所示,vector和string類型提供了一些成員函數,允許我們與它的實現中內存分配部分互動。capacity操作告訴我們容器在不擴張內存空間的情況下可以容納多少個元素。reserve操作允許我們通知容器它應該準備保存多少個元素。

  • 有當需要的內存空間超過當前容量時,reserve調用才會改變vector的容量。如果需求大小大于當前容量,reserve至少分配與需求一樣大的內存空間(可能更大)。如果需求大小小于或等于當前容量,reserve什么也不做。特別是,當需求大小小于當前容量時,容器不會退回內存空間。因此,在調用reserve之后,capacity將會大于或等于傳遞給reserve的參數。這樣,調用reserve永遠也不會減少容器占用的內存空間。類似的,resize成員函數(參見9.3.5節,第314頁)只改變容器中元素的數目,而不是容器的容量。我們同樣不能使用resize來減少容器預留的內存空間。
  • 在新標準庫中,我們可以調用shrink_to_fit來要求deque、vector或string退回不需要的內存空間。此函數指出我們不再需要任何多余的內存空間。但是,具體的實現可以選擇忽略此請求。也就是說,調用shrink_to_fit也并不保證一定退回內存空間。

capacity和size

  • 理解capacity和size的區別非常重要。容器的size是指它已經保存的元素的數目;而capacity則是在不分配新的內存空間的前提下它最多可以保存多少元素。下面的代碼展示了size和capacity之間的相互作用
vector<int> ivec;
//size 應該為0 capacity應該依賴于具體實現
cout << "ivec:size: " <<ivec.size()<< "capacity: "  <<ivec.capacity() << endl;
//向ivec 添加24個元素
for(vector<int>::size_type ix = 0; ix != 24; ix++){ivec.push_back(ix);
}
//size 應該為24 capacity應該大于等于24 具體依賴于標準庫的實現
cout << "ivec:size: " <<ivec.size()<< "capacity: "  <<ivec.capacity() << endl;
  • 當在我們的系統上運行時,這段程序得到如下輸出:
  • ivec:size:0 capacity:0
  • ivec:size:24 capacity:32
  • 我們知道一個空vector的size為0,顯然在我們的標準庫實現中一個空vector的capacity也為0。當向vector中添加元素時,我們知道size與添加的元素數目相等。而capacity至少與size一樣大,具體會分配多少額外空間則視標準庫具體實現而定。在我們的標準庫實現中,每次添加1個元素,共添加24個元素,會使capacity變為32。可以想象ivec的當前狀態如下圖所示:

  • 現在可以預先分配一些額外的空間
  • ivec.reserve(50);//將capacity的容量設置至少為50 可能會更大
  • size的大小應該為24,capacity的大小應該大于等于50 具體依賴于標準庫的實現
  • 添加元素用光預留空間 while(ivec.size() != ivec.capacity()){ ivec.push_back(0);}
  • 只要使用的空間沒有超過vector的容量,就不需要為此重新分配空間
  • 使用shrink_to_fit將vector超出當前大小的多余內存空間退回給系統
  • ivec.shrink_to_fit(); 要求歸還內存。這僅僅是一個請求,是否歸還并無保證
  • 每個vector實現都可以選擇自己的內存分配策略。但是必須遵守的一條原則 ,是 :只有當迫不得已時才可以分配新的內存空間
  • 只有在執行insert操作時size與capacity相等,或者調用resize或reserve時給定的大小超過當前capacity,vector才可能重新分配內存空間。會分配多少超過給定容量的額外空間,取決于具體實現。
  • 雖然不同的實現可以采用不同的分配策略,但所有實現都應遵循一個原則:確保用push_back向vector添加元素的操作有高效率。從技術角度說,就是通過在一個初始為空的vector上調用n次push_back來創建一個n個元素的vector,所花費的時間不能超過n的常數倍

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/446717.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/446717.shtml
英文地址,請注明出處:http://en.pswp.cn/news/446717.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

codeforces 281A-C語言解題報告

281A題目網址 題目解析 1.字符串首字母大寫 代碼 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> int main() {char s[1000]{\0};scanf("%s",s);if(s[0]>A&&s[0]<Z){printf("%s",s…

SpringBoot 配置文件bootstrap和application的區別

目錄一、SpringBoot配置文件二、bootstrap和application區別三、bootstrap和application的應用場景一、SpringBoot配置文件 bootstrap&#xff08;.yml 或者 .properties&#xff09; application&#xff08;.yml 或者 .properties&#xff09; 二、bootstrap和application區…

C++primer第九章 順序容器 9.5 額外的string操作

除了順序容器共同的操作之外&#xff0c;string類型還提供了一些額外的操作。這些操作中 的大部分要么是提供string類和C 風格字符數組之間的相互轉換,要么是增加了允許我們用下標代替迭代器的版本。標準庫string類型定義了大量函數。幸運的是&#xff0c;這些函數使用了重復的…

Zookeeper Mac下安裝操作

目錄一、下載Zookeeper二、修改配置1、設置啟動配置文件2、修改配置三、啟動Zookeeper服務命令1、bin目錄下執行&#xff08;1&#xff09;啟動Zookeeper命令&#xff08;2&#xff09;查看Zookeeper狀態命令&#xff08;3&#xff09;停止Zookeeper命令2、配置環境變量執行&am…

codeforces 266A-C語言解題報告

266A題目網址 題目解析 1.輸入n(1–50)個石頭個數,輸入RGB的石頭顏色,求問拿走最小的石頭個數,讓它們相鄰的石頭顏色不同 代碼 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {int n,i,count0;char s[50]{\0};scanf("%d&quo…

2014年考研英語二作文PartB圖表題

作文詳細解析 題目 Write an essay based on the following chart, in which you should interpret the chart, and give your comments You should write about 150 words on the ANSWER SHEET.(15 points) 注意點 1.圖表題在第一段描述圖表信息時,一定要寫清楚y軸變化…

Zookeeper 終端命令

目錄一、服務端命令1、啟動Zookeeper服務命令2、查看Zookeeper狀態命令3、停止Zookeeper服務命令4、啟動Zookeeper客戶端命令二、客戶端命令1、查看幫助2、查看當前znode所包含的內容3、創建znode4、創建短暫znode5、創建帶序號znode6、創建短暫帶序號znode7、獲取znode數據8、…

C++primer第九章 順序容器 9.6 容器適配器

9.6容器適配器 除了順序容器外&#xff0c;標準庫還定義了三個順序容器適配器&#xff1a;stack、queue和priority_queue適配器(adaptor)是標準庫中的一個通用概念。容器、迭代器和函數<369I都有適配器。本質上&#xff0c;一個適配器是一種機制&#xff0c;能使某種事物的…

codeforces 236A-C語言解題報告

236題目網址 題目解析 1.輸入字符串,判斷其中不同的字符個數,奇偶輸出不同的語句 2.使用冒泡排序去排序,當遇到s[k]!s[k1]時進行計數 代碼 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {char s [100]{\0};int i,j,k,count0;cha…

SpringBoot Controller接收參數的常用方式

文章目錄一、請求路徑參數1、PathVariable二、Body參數1、RequestParam2、RequestBody三、請求頭參數和Cookie參數1、RequestHeader2、CookieValue一、請求路徑參數 1、PathVariable 注解為&#xff1a; org.springframework.web.bind.annotation.PathVariable獲取路徑參數&…

C++primer第十章 泛型算法 10.1 概述 10.2 初識泛型算法

大多數算法都定義在頭文件algorithm中。標準庫還在頭文件numeric中定義了 一組數值泛型算法一般情況下&#xff0c;這些算法并不直接操作容器&#xff0c;而是遍歷由兩個迭代器指定的一個元素范圍(參見9.2.1節&#xff0c;第296頁)來進行操作。通常情況下&#xff0c;算法遍歷范…

MySQL Mac安裝教程

文章目錄一、下載安裝包二、安裝三、啟動MySQL四、環境變量設置一、下載安裝包 下載地址&#xff1a;https://downloads.mysql.com/archives/community/ 二、安裝 雙擊安裝包&#xff0c;然后一直點繼續即可。 三、啟動MySQL 打開 系統偏好設置&#xff0c;會發現多了一個…

codeforces 96A-C語言解題報告

96A題目網址 題目解析 1.輸入0和1表示不同隊的隊員字符串,如果7個及以上的一個0或1在一起,則輸出YES否則輸出NO 舉例: 輸入: 1000000001 輸出: YES 2.循環時,當遇到count7時輸出YES并跳出循環,遇到s[i]!s[i1]時,將count重置為1,最后count<7再輸出NO 代碼 #include<s…

C++生成指定范圍內的隨機數

代碼 rand&#xff08;&#xff09;% 3 &#xff1b; 3就是范圍&#xff0c;代表生成[0,3)之間的隨機數 int main(){for (int i 0; i < 20; i) {switch (rand() % 3) {case 0:std::cout << "00" << std::endl;case 1:std::cout << "11&q…

MySQL 客戶端命令

文章目錄1、連接命令2、斷開連接3、命令結束符4、查看所有數據庫5、切換到指定數據庫6、查看當前使用的數據庫7、查看庫中所有表8、查看所有用戶9、執行SQL腳本10、查詢當前時間1、連接命令 首先定位到MySQL安裝根目錄/bin目錄下&#xff0c;然后執行如下命令&#xff1a; my…

SQL 庫、表語句

文章目錄一、數據庫操作1、創建數據庫2、刪除數據庫二、表操作1、創建表&#xff08;1&#xff09;主鍵&#xff08;primary key&#xff09;屬性&#xff08;2&#xff09;unique屬性&#xff08;3&#xff09;主鍵和unique約束的區別&#xff08;4&#xff09;外鍵&#xff0…

codeforces 69A-C語言解題報告

69A題目網址 題目解析 1.輸入n個(x,y,z),當xi相加0;yi相加0;zi相加0同時時輸出YES,否則輸出NO 舉例: 輸入: 3 3 -1 7 -5 2 -4 2 -1 -3 輸出: YES 2.注意點:使用二維數組去存放時,使用遍歷行并對每一列分別相加 for(b0;b<n;b){count_xdir[b][0];count_ydir[b][1];count_z…

C++primer第十章 泛型算法 10.3 定制操作

10.3定制操作 很多算法都會比較輸入序列中的元素。默認情況下&#xff0c;這類算法使用元素類型的&#xff1c;或運算符完成比較。標準庫還為這些算法定義了額外的版本&#xff0c;允許我們提供自己定義的操作來代替默認運算符。例如&#xff0c;sort算法默認使用元素類型的&l…

SQL 查詢語句

文章目錄1、簡單查詢2、去除單列的重復結果查詢3、去除多列的重復結果查詢4、限制查詢結果條數5、對查詢結果排序&#xff08;1&#xff09;按照單個列的值進行排序&#xff08;2&#xff09;按照多個列的值進行排序6、帶搜索條件查詢&#xff08;1&#xff09;簡單搜索條件查詢…

2000年考研英語閱讀理解文章一

文章詳細講解網址 注意點 1.文章開篇第一句話往往是文章所想要通過后面講解的事情表達出來的最終觀點 2.當詢問到作者觀點時,往往在最后一段,一般以下形式呈現: 1)few people …(這就是作者的觀點) 2)I think 后面舉什么別人所說的話,如果不是表達了贊同,則都是別人的觀點,而…