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