習(xí)(構(gòu)造函數(shù)、迭代器、容量操作、增刪查改,迭代器失效和二維vector))
文章目錄前言一、vector 是什么二、vector 的構(gòu)造函數(shù)三、vector 迭代器1、四種迭代器2、四種遍歷方式四、vector 容量操作1、函數(shù)使用2、vector 的擴(kuò)容機(jī)制了解3、優(yōu)化效率技巧提前 reserve五、vector 增刪查改1、接口總覽2、代碼使用六、大坑vector 迭代器失效1、什么是迭代器失效2、兩種導(dǎo)致失效的場景場景 1擴(kuò)容導(dǎo)致失效空間變了場景 2erase 刪除導(dǎo)致失效位置變了3、迭代器失效的通用解決辦法七、vector 二維數(shù)組以楊輝三角為例1、基本用法2、經(jīng)典案例楊輝三角總結(jié)前言C 語言里我們用數(shù)組大小固定想擴(kuò)容就得手動(dòng)realloc又麻煩又容易出錯(cuò)。到了 C有了vector—— 一個(gè)可以自動(dòng)增長的動(dòng)態(tài)數(shù)組不用自己管內(nèi)存想加就加、想刪就刪可以說非常方便。本文主要講解構(gòu)造函數(shù)、迭代器、容量操作、增刪查改迭代器失效和二維vector等內(nèi)容幫助新手快速入門。提示以下是本篇文章正文內(nèi)容下面案例可供參考一、vector 是什么vector 英文翻譯過來叫“向量”你可以把它理解成一個(gè)可以自動(dòng)擴(kuò)容的動(dòng)態(tài)數(shù)組。和普通數(shù)組比vector有三大優(yōu)勢自動(dòng)管理內(nèi)存不用手動(dòng)申請釋放內(nèi)存空間不夠會(huì)自動(dòng)擴(kuò)容支持隨機(jī)訪問和數(shù)組一樣可以用方括號[]下標(biāo)訪問豐富的接口插入、刪除、查找、交換…… 全都有現(xiàn)成的。使用 vector 需要包含頭文件#include vector且在std命名空間下。二、vector 的構(gòu)造函數(shù)vector 有多種構(gòu)造方式最常用的有 4 種構(gòu)造函數(shù)功能說明vectorT v無參構(gòu)造一個(gè)沒有數(shù)據(jù)的 vectorvectorT v(n, val)構(gòu)造一個(gè)有 n 個(gè)元素的值為 val 的 vectorvectorT v(v2)拷貝構(gòu)造vectorT v(first, last)用迭代器區(qū)間構(gòu)造補(bǔ)充vectorT v(n, val)也可以不傳 val用vectorT v(n)表示構(gòu)造一個(gè)有 n 個(gè)元素的值為 0 的vector。T表示傳入的數(shù)據(jù)類型。#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv1;// 空的int vector//vectorint v2(5); // 5個(gè)0vectorintv2(5,10);// 5個(gè)10vectorintv3(v2);// 拷貝構(gòu)造v3vectorintv4(v2.begin(),v2.end());// 迭代器區(qū)間構(gòu)造// 還可以用數(shù)組構(gòu)造intarr[]{1,2,3,4,5};vectorintv5(arr,arrsizeof(arr)/sizeof(int));return0;}三、vector 迭代器迭代器是 STL 的通用遍歷方式vector 的迭代器本質(zhì)就是原生指針用起來非常方便。1、四種迭代器迭代器功能begin() / end()正向迭代器begin 指向第一個(gè)元素end 指向最后一個(gè)元素的下一個(gè)位置rbegin() / rend()反向迭代器rbegin 指向最后一個(gè)元素rend 指向第一個(gè)元素的前一個(gè)位置cbegin() / cend()const 正向迭代器只讀不可改crbegin() / crend()const 反向迭代器也是只讀不可改注end()、rend() 都是哨兵位迭代器不指向有效元素因此不能被解引用。2、四種遍歷方式#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);// 方式1下標(biāo)[]遍歷最常用像數(shù)組一樣for(size_t i0;iv.size();i)coutv[i] ;coutendl;// 方式2正向迭代器vectorint::iterator itv.begin();while(it!v.end()){cout*it ;it;}coutendl;// 方式3反向迭代器從后往前vectorint::reverse_iterator ritv.rbegin();while(rit!v.rend()){cout*rit ;rit;}coutendl;// 方式4范圍for最簡潔的方法是C11新增的語法for(autoe:v)coute ;coutendl;return0;}技巧點(diǎn)用auto自動(dòng)推導(dǎo)迭代器類型不用寫長長的vectorint::iterator。四、vector 容量操作函數(shù)功能說明size()返回有效元素個(gè)數(shù)capacity()返回底層總?cè)萘縠mpty()判斷vector是否為空resize(n, val)把有效元素個(gè)數(shù)改成 n多出的用 val 填充reserve(n)預(yù)留 n 個(gè)元素的空間只改容量不改有效個(gè)數(shù)1、函數(shù)使用#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv;coutv.size()endl;// 0coutv.capacity()endl;// 0coutv.empty()endl;// 1空v.push_back(1);v.push_back(2);v.push_back(3);coutv.size()endl;// 3coutv.capacity()endl;// 容量自動(dòng)擴(kuò)容大于等于size// resize改變有效元素個(gè)數(shù)v.resize(5,0);// 變成5個(gè)元素新增的位置用0填充 → 1 2 3 0 0v.resize(2);// 變成2個(gè)元素 → 1 2coutv.capacity()endl;// 注意resize只改sizecapacity不會(huì)縮小// reserve只預(yù)留空間不改sizev.reserve(100);// 容量變成100但size還是2coutv.size()endl;// 2coutv.capacity()endl;// 100return0;}2、vector 的擴(kuò)容機(jī)制了解vector 空間不夠時(shí)會(huì)自動(dòng)擴(kuò)容但不同編譯器擴(kuò)容倍數(shù)不一樣VSPJ 版 STL按1.5 倍擴(kuò)容GSGI 版 STL按2 倍擴(kuò)容這里用 VS 來演示#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv;size_t szv.capacity();coutmaking v grow:endl;for(inti0;i100;i){v.push_back(i);if(sz!v.capacity()){szv.capacity();coutcapacity changed: szendl;}}return0;}3、優(yōu)化效率技巧提前 reserve在使用vector處理大量數(shù)據(jù)時(shí)如果知道大概要存多少個(gè)元素提前用reserve預(yù)留空間可以避免邊插入邊擴(kuò)容大幅提升效率。intmain(){vectorintv;v.reserve(100);// 提前預(yù)留100個(gè)空間for(inti0;i100;i)v.push_back(i);// 全程不擴(kuò)容效率高return0;}五、vector 增刪查改1、接口總覽函數(shù)功能說明push_back(x)尾插一個(gè)元素最常用pop_back()尾刪一個(gè)元素insert(pos, x)在 pos 位置前插入元素 xerase(pos)刪除 pos 位置的元素swap(v)交換兩個(gè) vector 的內(nèi)容operator[]下標(biāo)訪問最常用find(first, last, x)查找元素算法庫函數(shù)不是成員函數(shù)注意find函數(shù)在algorithm頭文件里不是 vector 的成員函數(shù)2、代碼使用#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv;// 尾插v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);// v: 1 2 3 4// 尾刪v.pop_back();// v: 1 2 3// 任意位置插入v.insert(v.begin(),0);// 開頭插入0 → 0 1 2 3v.insert(v.begin()2,99);// 第3個(gè)位置插入99 → 0 1 99 2 3// 任意位置刪除v.erase(v.begin());// 刪除第一個(gè) → 1 99 2 3v.erase(v.begin()1);// 刪除第二個(gè) → 1 2 3// 查找注意find是算法庫的不是vector的成員函數(shù)autoposfind(v.begin(),v.end(),2);if(pos!v.end())cout找到了下標(biāo)pos-v.begin()endl;// 交換vectorintv2(5,10);v.swap(v2);// 交換v和v2的內(nèi)容return0;}六、大坑vector 迭代器失效1、什么是迭代器失效vector 的迭代器本質(zhì)就是指針。迭代器失效 迭代器指向的空間被釋放了再用就會(huì)訪問非法內(nèi)存程序崩潰。2、兩種導(dǎo)致失效的場景場景 1擴(kuò)容導(dǎo)致失效空間變了所有可能引起底層空間改變的操作都可能導(dǎo)致迭代器失效resize、reserve、insert、push_back、assign等。#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv{1,2,3,4,5};autoitv.begin();v.reserve(100);// 擴(kuò)容舊空間被釋放it失效了// 再用it就是非法訪問程序崩潰while(it!v.end()){cout*it ;it;}return0;}原因擴(kuò)容時(shí)開了新空間、釋放了舊空間而it還指向舊空間的地址。場景 2erase 刪除導(dǎo)致失效位置變了erase刪除元素后后面的元素會(huì)往前搬移。如果刪除的是最后一個(gè)元素刪完后pos剛好等于end就失效了。以下是錯(cuò)誤的寫法#includeiostream#includevectorusingnamespacestd;// 錯(cuò)誤寫法刪除所有偶數(shù)會(huì)崩潰或結(jié)果不對intmain(){vectorintv{1,2,3,4};autoitv.begin();while(it!v.end()){if(*it%20)v.erase(it);// erase后it失效了it;// 失效的迭代器再會(huì)崩潰或者結(jié)果與預(yù)期不符}return0;}正確操作是接收erase返回值erase會(huì)返回下一個(gè)有效位置的迭代器用返回值更新it就不會(huì)失效了。以下是正確的寫法#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv{1,2,3,4};autoitv.begin();while(it!v.end()){if(*it%20)itv.erase(it);// 用返回值更新itelseit;}return0;}3、迭代器失效的通用解決辦法操作完之后如果還要用迭代器重新賦值一下就好。比如擴(kuò)容之后重新it v.begin();就不會(huì)有問題了。#includeiostream#includevectorusingnamespacestd;intmain(){vectorintv{1,2,3,4,5};autoitv.begin();v.reserve(100);// 擴(kuò)容舊空間被釋放it失效了itv.begin();// 重新賦值while(it!v.end()){cout*it ;it;}return0;}七、vector 二維數(shù)組以楊輝三角為例vector 的元素也可以是 vector這樣就形成了二維數(shù)組而且每行長度可以不一樣比 C 語言的二維數(shù)組靈活多了。1、基本用法#includeiostream#includevectorusingnamespacestd;intmain(){// 3行的二維數(shù)組每行是一個(gè)vectorintvectorvectorintvv(3);vv[0].push_back(1);vv[1].push_back(1);vv[1].push_back(2);vv[2].push_back(1);vv[2].push_back(2);vv[2].push_back(3);// 遍歷二維vectorfor(size_t i0;ivv.size();i){for(size_t j0;jvv[i].size();j)coutvv[i][j] ;coutendl;}return0;}2、經(jīng)典案例楊輝三角118. 楊輝三角classSolution{public:vectorvectorintgenerate(intnumRows){vectorvectorintvv(numRows);// 每行大小設(shè)為i1全部初始化為1for(inti0;inumRows;i)vv[i].resize(i1,1);// 中間元素 上一行兩個(gè)相加for(inti2;inumRows;i)for(intj1;ji;j)vv[i][j]vv[i-1][j]vv[i-1][j-1];returnvv;}};119. 楊輝三角 IIclassSolution{public:vectorintgetRow(introwIndex){vectorvectorintvv(rowIndex1);// 每行大小設(shè)為i1全部初始化為1for(inti0;irowIndex;i)vv[i].resize(i1,1);// 中間元素 上一行兩個(gè)相加for(inti2;irowIndex;i)for(intj1;ji;j)vv[i][j]vv[i-1][j]vv[i-1][j-1];returnvv[rowIndex];}};總結(jié)本文主要是講解了vector容器的用法和新手可能遇到的坑希望對大家有所幫助。