[c++]—vector類___基礎版(帶你了解vector熟練掌握運用)

👩🏻?💻作者:chlorine

目錄

🎓標準庫類型vector

🎓定義和初始化vector的對象

💻列表初始化vector對象

💻創建指定數量的元素

🕶?值初始化

?列表初始化還是值初始化?

🎓向vector對象中添加元素

💻關鍵概念:vector對象能高效增長

🎓其他vector操作

💻計算vector內對象的索引

🕶?不能用下標形式添加數據


🎓標準庫類型vector

vector標準庫類型表示對象的集合,其中所有對象的類型都相同。集合中的每個對象都有一個與之對應的索引,索引用于訪問對象。因為vector"容納著”其他對象,所以它也常常被稱作容器(container).

要想用vector,必須包含適當的頭文件,再后續的例子中,都將假定做了如下using聲明:

#include<vector>
using std::vector;

c++語言既有類模板(class template),也有函數模板,其中vector就是一個類模板。

只有對c++有了深入的理解才能寫出模板,但是后期我們會學,但是幸運的是,我們即使不會創建類模板,我們可以先試著去使用它。

模板本身不是類或函數,相反可以將模板看作為編譯器生成類或函數編寫的一份說明。編譯器根據模板創建類或函數的過程就是實例化,當使用模板的時候,需要指出編譯器應把類或函數實例化稱某種類型。

對于類模板來說,我們通過提供一些額外信息來指定模板到底實例化成什么樣的類,需要提供哪些信息由模板決定,提供信息的方式總是這樣:即在模板名字后面跟一對尖括號,在括號內放上信息。以vector為例,提供的額外信息是vector內所存放對象的類型:

vector<int>iverc;//iverc保存int類型的對象
vector<vector<int>>file;//該向量的元素是vector對象

注意:vector是模板而非類型,由vector生成的類型必須包含vector中元素的類型,例如vector<int>.


🎓定義和初始化vector的對象

和任何一種類類型一樣,vector模板控制著定義和初始化向量的方法。

vector<T> v1; //v1是空vector,它潛在的元素是T類型的,執行默認初始化.
vector<T> v2(v1);//v2中包含v1所有元素的副本
vector<T> v2 = v1;//等價于v2(v1),v2中包含v1所有元素的副本
vector<T> v3(n, val);//v3包含了n個重復的元素,每個元素的值都是val
vector<T> v4(n); //v4包含了n個重復執行了值初始化的對象
vector<T> v5{a,b,c...}//v5包含了初始值個數的元素,每個元素賦予了相應的初始值
vector<T> v5={ a,b,c... } //等價于 v5{a,b,c...}

可以默認初始化vector對象,從而創建一個指定類型的空vector。

vector<string> svec;//默認初始化,svec不含任何元素

看起來空vector好像沒什么用,但是很快我們就會知道程序在運行時可以很高效地往往vector對象中添加元素,事實上,最常見地方式就是先定義一個空vector,然后再運行地時候獲取到元素地值后逐一添加。當然我們也可以再定義vector對象時指定元素地初始值。例如:允許把一個vector對象地元素拷貝給另外一個vector對象。此時,新vector對象地元素就是原vector對象對應元素地副本,注意倆個vector對象地類型必須相同。

vector<int> ivec;//初始狀態為空
//再此處給ivec添加一些值
vector<int>ivec2(ivec);
vector<int>ivec3 = ivec;
vector<string>svec(ievc2);//錯誤:svec的元素是string對象,不是int

💻列表初始化vector對象

c++11新標準還提供另外一種為vector對象的元素賦初值的方法,即列表初始化。此時,用花括號括起來的0個或多個初始元素值被賦給vector對象:

vector<string> articles = { "a","an","the" };

上述vector對象包含三個元素:第一個字符串"a",第二個是字符串"an",第三個字符串是“the”。

c++提供了幾種不同的初始化方式,大多數情況瞎這些初始化方式可以相互的等價的使用,不過也并非一直如此。其一:使用拷貝初始化時(即使用=時)只能提供一個初始值;其二:如果提供的是一個類內初始值,則只能使用拷貝初始化或使用花括號的形式初始化。第三種特殊的要求是,如果提供的是初始元素值得列表,則只能把初始值都放在花括號里進行列表初始化,而不能放在圓括號里:

vector<string> v1{ "a","an","the" };//列表初始化
vector<string> v1( "a","an","the" );//錯誤

💻創建指定數量的元素

還可以用vector對象容納的元素數量和所有元素的統一初始值來初始化vecotor對象。

vector<int> v1(10, -1);//10個int類型的元素,每個值都初始化為-1
vector<string> svec(10, "hi");//10個string類型的元素,每個初始化為"hi"

🕶?值初始化

通常情況下,可以只提供vector對象容納的元素數量而略去初始值,此時庫就會創建一個值初始化元素初值,并把它賦給容器中的所有元素,這個初值由vector對象中元素的類型決定。

  • 如果vector對象的元素是內置類型,比如int,則元素初始值自動設為0。
  • 如果元素是某種類類型,比如string<=,則元素由類默認初始化
vector<int> ivec(10);//10個元素,每個都初始化為0
vector<string> svec(10);//10個元素,每個都是空string對象

對這種初始化的方式有倆個特殊限制,其一:有些類要求必須明確提供初始值,如果vector對象中元素的類型不支持默認初始化,我們就必須提供初始化的元素值,對這種類型的對象來說,只提供元素的數量而不設定初始值無法完成初始化工作。

其二:如果只提供了元素的數量而沒有設定初始值,只能使用直接初始化。

vector<int> v1=10;//錯誤:必須使用直接初始化的形式指定向量大小

這里的10是用來說明如何初始化vector對象的,我們用它的本意是想創建含有10個值初始化了的元素的vector對象,而非把數字10"拷貝“到vector中,因此,此時不宜使用拷貝初始化。


?列表初始化還是值初始化?

在某種情況下,初始化的真正含義依賴于傳遞初始值時用的是花括號還是圓括號。

例如,用一個整數來初始化vector<int>時,整數的含義可能是vector對象的容量也可能是元素的值。類似的,用倆個整數來初始化vector<int>時,這倆個整數可能一個是vector對象的容量,另一個是元素的初值,也可能它們是容量為2的vector對象中的倆個元素的初值。通過使用花括號或圓括號可以區分上述這些含義:

vector<int> v1(10);//v1有10個元素,每一個元素都是0(默認初始化)vector<int> v2{ 10 };//v1有1個元素,該元素的值是10vector<int> v3(10, 1);//v3有10個元素,每個值都是1vector<int> v4{ 10,1 };//v4有2個元素,值分別是10和1


另一方面,如果初始化時使用花括號的形式但是提供的值又不能用來列表初始化,就要考慮用這樣的值來構造vector對象了,例如:要想列表初始化一個含有string對象的vector對象,應該提供能賦給string對象的初值。此時不難區分到底是要列表初始化vector對象的元素還是用給定的容量值來構造vector對象。

vector<string> v5{ "h1" };//列表初始化:v5有一個元素vector<string> v6("h1");//錯誤,不能使用字符串字面值構建vector對象vector<string> v7{ 10 };//v7有10個默認初始化的元素vector<string> v8{ 10,"h1" };//v8有10個值為"h1"的元素


🎓向vector對象中添加元素

對vector對象而言,直接初始化的方式適用于三種情況:1.初始值已知且數量較少2.初始值是另一個vector對象的副本3.所有元素的初始值都一樣。然而最常見的情況是:有些時候即使元素的初值已知,但如果這些值總量較大而各不相同,那么在創建vector對象的時候執行初始化操作也會顯得過于繁瑣。

舉個例子,如果想創建一個vector對象令其包含從0到9共10個元素,使用列表初始化的方法很容易做到一點,但如果vector對象包含的元素是從0到99或者從0到999呢?這時通過列表初始化把所有元素都一一羅列出來就不太合適了,對于此例來說,更好的處理方法是先創建一個空vector,然后再運行的時再利用vector的成員函數push_back向其添加元素。push_back負責把一個值當成vector對象的尾元素"壓到(push)"vector對象的"尾端(back)",例如:

vector<int> v1;for (int i = 0; i <= 100; i++){v1.push_back(i);//依次把整數值放到v2尾端}//循環結束后v2有100個元素,值從0-99

在上例中,盡管知道vector對象最后會包含100個元素,但在一開始還是把它聲明成空vector,在每次迭代時才順序地把下一個整數作為v1的新元素添加給它。

同樣的,如果直到運行的時候才能知道vector對象中元素的確切個數。也應該使用剛剛這種方法的創建vector對象并為其賦值。例如:有時候需要實時讀入數據然后將其賦予vector對象。

//從標準輸入中輸入單詞,將其作為vector對象的元素存儲string word;vector<string>text;//空vector對象while (cin >> word){text.push_back(word);//把word添加到text后面}for (auto e : text){cout << e << " ";}

和之前的例子一樣,本例 也是先創建一個空vector,之后依次讀入未知數量的值并保存到vector中。

當執行程序時,運行到while循環,會一直讀取字符,讀完字符后,如果要結束此循環,先按Enter鍵,再按Ctrl+Z最后按一次Enter就能跳出while循環。


💻關鍵概念:vector對象能高效增長

c++標準要求vector應該能在運行時高效快速的增加元素,因此既然vector對象能高效地增長,那么在定義vector對象的時候設定其大小也就沒什么必要了,事實上如果這么做性能可能更差。只有一種例外情況,就是所有(all)元素的值都一樣。一旦元素的值各有不同,更有效的方法就是先定義一個空的vector對象,再在運行時向其添加具體值。

開始的時候創建空的vector對象,在運行時再動態添加元素。

    int v1;vector<int> v;//定義一個空vector對象while (cin >>v1)//依次輸入v1{v.push_back(v1);//然后v1的值依次存儲再vector對象中}for (auto e : v){cout << e << " ";}


🎓其他vector操作

除push_back之外,vector還提供了幾種其他操作,大多數都和string的相關操作類似。

v.empty()  如果v不含有任何元素,返回真;否則返回假
v.size()    返回v中元素的個數
v.push_back(t)  向v的尾端添加一個值為t的元素
v[n]        返回v的第n個位置上的元素的引用
v1=v2      用v2中元素的拷貝替換v1中的元素
v1={a,b,c,d...}  用列表中元素的拷貝替換v1中的元素
v1==v2      v1和v2相等當且僅當它們的元素數量相同且對應位置的元素值都相同
v1!=v2
< <= > >= 顧名思義,以字典順序進行比較

訪問vector對象中元素的方法和訪問string對象中字符的方法差不多,也是通過元素在vector對象中的位置。例如,可以使用范圍for語句處理vector對象中所有元素。

int main()
{vector<int> v{ 1,2,3,4,5,6 };for (auto& i : v)//對于v中的每個元素(注意:i是一個引用){i *= i;//求元素值的平方}for (auto i : v) //對于v中的每個元素{cout << i << " ";//輸出該元素}cout << endl;return 0;
}

第一個循環給控制變量i定義成引用類型,這樣就能通過i給v的元素賦值,其中i的類型由auto關鍵字指定。這里用到一個新的復合賦值運算符,如我們所知,+=把左側運算對象和右側運算對象相加,結果存入左側運算對象,類似的,*=把左側運算對象和右側運算對象相乘,結果存入左側運算對象,最后,第二個循環輸出所有的值。

vector的empty和size倆個成員與string的同名成員功能完全一致。empty檢查vector對象是否包含元素然后返回一個布爾值,size則返回vector對象中元素的個數,返回值的類型是由vector定義的size_type類型。

要使用size_type,需首先指定它是由哪種類型定義的,vector對象的類型總是包含著元素的類型

vector<int>::size_type   //正確
vector::size_type     //錯誤

各個相等性運算符和關系運算符也與string的相應的運算符功能一致。倆個vector對象相等當且僅當它們所含的元素個數相同,而且對應位置的元素值也相同。關系運算符依照字典順序進行比較:如果倆個vector對象的容量不同,但是在相同的位置上的元素值都一樣,則元素較少的vector對象小于元素較多的vector對象;若元素的值有區別,則vector對象的大小關系由第一對相異的元素值的大小關系決定。

只有當元素的值可比較時,vector對象才能被比較。一些類,如string等。確定定義了自己的相等性運算符和關系運算符。


💻計算vector內對象的索引

使用下標運算符能獲取到指定的元素。和string一樣。vector對象的下標也是從0開始記起,下標的類型也是相應的size_type類型。只要vector對象不是一個常量,就能向下標運算符返回的元素賦值。此外,也能通過計算得到vector內對象的索引,然后直接獲取索引位置上的元素。

舉個例子,假設有一組成績的集合,其中成績的取值從0到100,以10分為一個分數段,要求統計各個分數段各有多少個成績。顯然,從0到100總共有101中可能的成績取值,這些成績分布在11個分數段中:每10個分數構成一個分數段,這樣的分數段有10個,額外還有一個分數段表示滿分100分。這樣第一個分數段將統計成績從0到9之間的數量;第二個分數段將統計成績在10到99之間的數量,以此類推,最后一個分數段統計滿分100分的數量。

以10分為一個分數段統計成績的數量:0~9,10~19,.....90~99,100(一共11個區間)

在具體實現時使用一個含有11個元素的vector對象,每個元素分別用于統計各個分數段上出現的成績個數。對于某個成績來說,將其除以10就能得到對應的分數段的索引。注意:倆個整數相除結果還是整數,余數部分被忽略掉了。42/10=4....一旦計算得到了分數的索引,就能用它作為vector對象的下標,進而獲取該分數段的計數值并加1。

vector<size_t> scores(11, 0);//11個分數段,并初始化為0size_t grade;while (cin >> grade){if (grade <= 100)   //只處理有效分數{++scores[grade / 10];  //將對應的分數段的計數值+1}}for (auto e : scores){cout << e << " ";}++scores[grade/10];倆者等價的
auto ind=grade/10;//得到分數段的索引
scores[ind]=scores[ind]+1;//將計數值加1


🕶?不能用下標形式添加數據

剛接觸c++語言的程序員也許認為可以通過vector對象的下標形式來添加元素,事實并非如此。下面的代碼試圖為vector對象ivec添加10個元素。

vector<int> ivec;//空的vector對象for (decltype(ivec.size())ix = 0; ix != 10; ix++){ivec[ix] = ix;}for (auto e : ivec){cout << e << " ";}

這段代碼是錯誤的,ivec是一個空vector,根本不包含任何元素,當然也就不能通過下標去訪問任何元素,如前所述,正確的方法是使用push_back;

vector<int> ivec;//空的vector對象for (decltype(ivec.size())ix = 0; ix != 10; ix++){//ivec[ix] = ix;//嚴重錯誤,ivec不包含任何元素ivec.push_back(ix);}for (auto e : ivec){cout << e << " ";}


vector對象(以及string對象)的下標運算符可用于訪問已存在的元素,而不能用于添加元素


提示:只能對已存在的元素執行下標操作

關于下標必須明確的一點是:只能對確知已存在的元素執行下標操作

vector<int>ivec;  //空vector對象
cout<<ivec[0];  //錯誤:ivec不包含任何元素vector<int>ivec(10);  //含有10個元素的vector對象
cout<<ivec[10];    //錯誤:ivec元素的合法索引是從0~9

試圖用下標的i形式去訪問一個不存在的元素將引發錯誤。不過這種情況不會再編譯的過程發現,而是再運行時候產生一個不可預知的值。

確保下標合法的一種有效手段就是盡可能使用范圍for


今天下雪了

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

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

相關文章

樹莓派,opencv,Picamera2利用舵機云臺追蹤特定顏色對象

一、需要準備的硬件 Raspiberry 4b兩個SG90 180度舵機&#xff08;注意舵機的角度&#xff0c;最好是180度且帶限位的&#xff0c;切勿選360度舵機&#xff09;二自由度舵機云臺&#xff08;如下圖&#xff09;Raspiberry CSI 攝像頭 組裝后的效果&#xff1a; 二、項目目標…

力扣labuladong一刷day30天二叉樹

力扣labuladong一刷day30天二叉樹 文章目錄 力扣labuladong一刷day30天二叉樹一、654. 最大二叉樹二、105. 從前序與中序遍歷序列構造二叉樹三、106. 從中序與后序遍歷序列構造二叉樹四、889. 根據前序和后序遍歷構造二叉樹 一、654. 最大二叉樹 題目鏈接&#xff1a;https://…

智慧機房與3D機房動環監控系統的應用

智慧機房是什么&#xff1f; 智慧機房是集采集信息、實時監控、數據分析、統一管理、故障告警等功能于一體的全方位、立體化的智能環境監控系統&#xff0c;構建物聯網、大數據和云計算背景下現代企業的“數據心臟”。它能為機房管理者呈現細致入微的關鍵性數據&#xff0c;優…

電子學會C/C++編程等級考試2022年06月(五級)真題解析

C/C++等級考試(1~8級)全部真題?點這里 第1題:逃離迷宮 你在一個地下迷宮中找到了寶藏,但是也觸發了迷宮機關,導致迷宮將在T分鐘后坍塌,為此你需要在T分鐘內逃離迷宮,你想知道你能不能逃離迷宮。迷宮是一個邊長為m的正方形,其中"S"表示你所在的位置,"…

<url-pattern>/</url-pattern>與<url-pattern>/*</url-pattern>的區別

<url-pattern>/</url-pattern> servlet的url-pattern設置為/時&#xff0c; 它僅替換servlet容器的默認內置servlet&#xff0c;用于處理所有與其他注冊的servlet不匹配的請求。直白點說就是&#xff0c;所有靜態資源&#xff08;js&#xff0c;css&#xff0c;ima…

HCIA-H12-811題目解析(9)

1、【單選題】下面選項中&#xff0c;能使一臺IP地址為10.0.0.1的主機訪問Interne的必要技術是&#xff1f; 2、【單選題】 FTP協議控制平面使用的端口號為&#xff1f; 3、【單選題】 使用FTP進行文件傳輸時&#xff0c;會建立多少個TCP連接&#xff1f; 4、【單選題】完成…

ubuntu apache2配置反向代理

1.Ubuntu安裝apache sudo apt-get update sudo apt-get install apache2 2.apache2反向代理配置 sudo vim /etc/apache2/sites-available/000-default.conf 添加內容如下&#xff1a; <VirtualHost *:80># The ServerName directive sets the request scheme, host…

目標檢測YOLO實戰應用案例100講-基于深度學習的SAR圖像艦船目標檢測(續)

目錄 4基于自注意力機制的YOLO-v3算法的SAR圖像目標檢測 4.1 YOLO系列發展現狀 4.2自注意力機制

做數據分析為何要學統計學(10)——如何進行時間序列分析

時間序列是由隨時間變化的值構成&#xff0c;如產品銷量、氣溫數據等等。通過對時間序列展開分析&#xff0c;能夠回答如下問題&#xff1a; &#xff08;1&#xff09;被研究對象的活動特征是否有周期性&#xff08;也稱季節性&#xff09;&#xff08;2&#xff09;被研究對…

學生成績管理系統詳細設計書

1. 引言 本學生成績管理系統旨在滿足學校對學生成績進行高效、精準、便捷管理的需求。通過系統化的管理方式&#xff0c;改善現有成績管理方式的不足&#xff0c;提高工作效率&#xff0c;同時保證學生成績信息的準確性和安全性。本詳細設計文檔將為系統的實現提供全面的指導和…

UE4/UE5 修改/還原場景所有Actor的材質

使用藍圖方法&#xff1a; 1.修改場景所有Actor 材質&#xff1a; Wirframe&#xff1a;一個材質類 MatList&#xff1a;獲取到的所有模型的全部材質 的列表 TempAllClass&#xff1a;場景中所有獲取的 Actor 的列表 功能方法如下&#xff1a; 藍圖代碼可復制在&#xff1a…

Unity之OpenXR+XR Interaction Toolkit接入微軟VR設備Windows Mixed Reality

前言 Windows Mixed Reality 是 Microsoft 用于增強和虛擬現實體驗的VR設備,如下圖所示: 在國內,它的使用率很低,一把都是國外使用,所以適配起來是相當費勁。 這臺VR設備只能用于串流Windows,啟動后,會自動連接Window的Mixed Reality程序,然后打開微軟的增強現實門戶…

1.2 輕量級數據交互格式–JSON

對于接口來說,數據交互大部分都是使用的JSON格式,我們這里說的數據,就是我們上一章里講解HTTP協議的時候,HTTP協議結構里的實體,也就是放在body里。body里存放需要傳輸的數據,數據是JSON格式,然后通過HTTP協議來傳輸給接口,接口再以同樣的方式給我們返回。理解了這一層…

網絡基礎(五):網絡層協議介紹

目錄 一、網絡層 1、網絡層的概念 2、網絡層功能 3、IP數據包格式 二、ICMP協議 1、ICMP的作用和功能 2、ping命令的使用 2.1ping命令的通用格式 2.2ping命令的常用參數 2.3TypeCode&#xff1a;查看不同功能的ICMP報文 2.4ping出現問題 3、Tracert 4、沖突域 5、…

LSU介紹

LSU&#xff08;Load Store Unit&#xff09;是一個專門的執行單元&#xff0c;負責執行所有的加載&#xff08;load&#xff09;和存儲&#xff08;store&#xff09;指令等&#xff0c;生成load和store操作的虛擬地址&#xff0c;并從內存中加載數據或將數據從寄存器中存儲回…

關于前端原生技術-Jsonp的理解與簡述

【版權聲明】未經博主同意&#xff0c;謝絕轉載&#xff01;&#xff08;請尊重原創&#xff0c;博主保留追究權&#xff09; https://blog.csdn.net/m0_69908381/article/details/134777717 出自【進步*于辰的博客】 在學習了Jsoup這個知識點之后&#xff0c;發覺js的這一特點…

基于appium的常用元素定位方法

一、元素定位工具   app應用的元素使用的是控件定位&#xff0c;不同于web網頁&#xff0c;web網頁定位元素通常使用的是F12工具&#xff0c;那么在app當中我們則要借助其它的工具來輔助定位。 1.uiautomatorviewer.bat   uiautomatorviewer.bat工具在安裝完ADT工具之后&a…

【Docker】進階之路:(十一)Docker存儲

【Docker】進階之路&#xff1a;&#xff08;十一&#xff09;Docker存儲 Docker存儲簡介storage driverdata volumevolumebind mounttmpfs mount Docker提供了4種存儲方式&#xff1a;默認存儲、volume(數據卷)、bind mounts(綁定掛載)、tmpfsmount(僅在Linux環境中提供)。其中…

Jemeter,提取響應體中的數據:正則表達式、Json提取器

一、正則表達式 1、線程組--創建線程組&#xff1b; 2、線程組--添加--取樣器--HTTP請求&#xff1b; 3、Http請求--添加--后置處理器--正則表達式提取器&#xff1b; 4、線程組--添加--監聽器--查看結果樹&#xff1b; 5、線程組--添加--取樣器--調試取樣器。 響應體數據…

docker mysql8 設置不區分大小寫

docker安裝Mysql8.0的坑之lower_case_table_names_docker mysql lower_case_table_names-CSDN博客https://blog.csdn.net/p793049488/article/details/108365929 docker run ‐di ‐‐nametensquare_mysql ‐p 33306:3306 ‐e MYSQL_ROOT_PASSWORD123456 mysql