【高級編程】C++中vector使用詳解

2021-12-26 程式設計師互動聯盟

1. 在C++中的詳細說明
vector是C++標準模板庫中的部分內容,它是一個多功能的,能夠操作多種數據結構和算法的模板類和函數庫。
vector之所以被認為是一個容器,是因為它能夠像容器一樣存放各種類型的對象,
簡單地說,vector是一個能夠存放任意類型的動態數組,能夠增加和壓縮數據。

2. 使用vector
必須在你的頭文件中包含下面的代碼:
#include <vector>
vector屬於std命名域的,因此需要通過命名限定,如下完成你的代碼:
  using std::vector;
  vector<int> vInts;
或者連在一起,使用全名:
std::vector<int> vInts;
建議使用全局的命名域方式:
using namespace std;

3. 初始化
vector <Elem> // 創建一個空的vector。
vector <Elem> c1(c2) // 複製一個vector
vector <Elem> c(n) // 創建一個vector,含有n個數據,數據均已預設構造產生
vector <Elem> c(n, elem) // 創建一個含有n個elem拷貝的vector
vector <Elem> c(beg,end) // 創建一個含有n個elem拷貝的vector

4. 析構函數
c.~vector <Elem>() // 銷毀所有數據,釋放內存

5. 成員函數
c.assign(beg,end) c.assign(n,elem)
將[beg; end)區間中的數據賦值給c。將n個elem的拷貝賦值給c。
c.at(idx)
傳回索引idx所指的數據,如果idx越界,拋出out_of_range。
c.back() // 傳回最後一個數據,不檢查這個數據是否存在。
c.begin() // 傳回迭代器中的第一個數據地址。
c.capacity() // 返回容器中數據個數。
c.clear() // 移除容器中所有數據。
c.empty() // 判斷容器是否為空。
c.end() // 指向迭代器中末端元素的下一個,指向一個不存在元素。
c.erase(pos) // 刪除pos位置的數據,傳回下一個數據的位置。
c.erase(beg,end) //刪除[beg,end)區間的數據,傳回下一個數據的位置。
c.front() // 傳回第一個數據。
get_allocator // 使用構造函數返回一個拷貝。
c.insert(pos,elem) // 在pos位置插入一個elem拷貝,傳回新數據位置。
c.insert(pos,n,elem) // 在pos位置插入n個elem數據。無返回值。
c.insert(pos,beg,end) // 在pos位置插入在[beg,end)區間的數據。無返回值。 
c.max_size() // 返回容器中最大數據的數量。
c.pop_back() // 刪除最後一個數據。
c.push_back(elem) // 在尾部加入一個數據。
c.rbegin() // 傳回一個逆向隊列的第一個數據。
c.rend() // 傳回一個逆向隊列的最後一個數據的下一個位置。
c.resize(num) // 重新指定隊列的長度。
c.reserve() // 保留適當的容量。
c.size() // 返回容器中實際數據的個數。
c1.swap(c2)
swap(c1,c2) // 將c1和c2元素互換。同上操作。
operator[] // 返回容器中指定位置的一個引用。

6. 用法示例:
6.1. 創建一個vector

vector容器提供了多種創建方法,下面介紹幾種常用的。
創建一個Widget類型的空的vector對象:
  vector<Widget> vWidgets;
創建一個包含500個Widget類型數據的vector:
  vector<Widget> vWidgets(500);
創建一個包含500個Widget類型數據的vector,並且都初始化為0:
  vector<Widget> vWidgets(500, Widget(0));
創建一個Widget的拷貝:
  vector<Widget> vWidgetsFromAnother(vWidgets);
向vector添加一個數據
  vector添加數據的預設方法是push_back()。
push_back()函數表示將數據添加到vector的尾部,並按需要來分配內存。

例如:向vector<Widget>中添加10個數據,需要如下編寫代碼:
  for(int i= 0;i<10; i++) {
   vWidgets.push_back(Widget(i));
  }


6.2 獲取vector中指定位置的數據
 vector裡面的數據是動態分配的,使用push_back()的一系列分配空間常常決定於文件或一些數據源。
如果想知道vector存放了多少數據,可以使用empty()。
獲取vector的大小,可以使用size()。
例如,如果想獲取一個vector v的大小,但不知道它是否為空,或者已經包含了數據,如果為空想設置為-1,
你可以使用下面的代碼實現:
  int nSize = v.empty() ? -1 : static_cast<int>(v.size());
  
6.3 訪問vector中的數據
使用兩種方法來訪問vector。
1、 vector::at()
2、 vector::operator[]
  operator[]主要是為了與C語言進行兼容。它可以像C語言數組一樣操作。
但at()是我們的首選,因為at()進行了邊界檢查,如果訪問超過了vector的範圍,將拋出一個例外。
由於operator[]容易造成一些錯誤,所有我們很少用它,下面進行驗證一下:
  
分析下面的代碼:
  vector<int> v;
  v.reserve(10);
for(int i=0; i<7; i++) {
   v.push_back(i);
  }
  
try {int iVal1 = v[7];
   // not bounds checked - will not throw
   int iVal2 = v.at(7);
   // bounds checked - will throw if out of range
  }

catch(const exception& e) {
   cout << e.what();
  }
  
6.3 刪除vector中的數據
vector能夠非常容易地添加數據,也能很方便地取出數據,
同樣vector提供了erase(),pop_back(),clear()來刪除數據,
當刪除數據時,應該知道要刪除尾部的數據,或者是刪除所有數據,還是個別的數據。

Remove_if()算法 如果要使用remove_if(),需要在頭文件中包含如下代碼::
  #include <algorithm>

Remove_if()有三個參數:
  1、 iterator _First:指向第一個數據的迭代指針。
  2、 iterator _Last:指向最後一個數據的迭代指針。
  3、 predicate _Pred:一個可以對迭代操作的條件函數。
  
6.4 條件函數
條件函數是一個按照用戶定義的條件返回是或否的結果,是最基本的函數指針,或是一個函數對象。
這個函數對象需要支持所有的函數調用操作,重載operator()()操作。
remove_if()是通過unary_function繼承下來的,允許傳遞數據作為條件。

例如,假如想從一個vector<CString>中刪除匹配的數據,如果字串中包含了一個值,從這個值開始,從這個值結束。
首先應該建立一個數據結構來包含這些數據,類似代碼如下:
#include <functional>
enum findmodes {
FM_INVALID = 0,
FM_IS,
 FM_STARTSWITH,
 FM_ENDSWITH,
 FM_CONTAINS
};

typedef struct tagFindStr {
 UINT iMode;
 CString szMatchStr;
} FindStr;


typedef FindStr* LPFINDSTR;
  
然後處理條件判斷:
class FindMatchingString : public std::unary_function<CString, bool> {
public:
 FindMatchingString(const LPFINDSTR lpFS) :
 m_lpFS(lpFS) {}
 bool operator()(CString& szStringToCompare) const {
  bool retVal = false;
  
switch (m_lpFS->iMode) {
  case FM_IS: {
   retVal = (szStringToCompare == m_lpFDD->szMatchStr);
   break;
  }
  case FM_STARTSWITH: {
   retVal = (szStringToCompare.Left(m_lpFDD->szMatchStr.GetLength())
   == m_lpFDD->szWindowTitle);
   break;
  }
  case FM_ENDSWITH: {
   retVal = (szStringToCompare.Right(m_lpFDD->szMatchStr.GetLength())
   == m_lpFDD->szMatchStr);
  break;
  }
  case FM_CONTAINS: {
   retVal = (szStringToCompare.Find(m_lpFDD->szMatchStr) != -1);
   break;
  }
  }
  return retVal;
}
private:
 LPFINDSTR m_lpFS;
};

通過這個操作你可以從vector中有效地刪除數據:
FindStr fs;
 fs.iMode = FM_CONTAINS;
 fs.szMatchStr = szRemove;
 vs.erase(std::remove_if(vs.begin(), vs.end(), FindMatchingString(&fs)), vs.end());
  
Remove(),remove_if()等所有的移出操作都是建立在一個迭代範圍上的,不能操作容器中的數據。
所以在使用remove_if(),實際上操作的時容器裡數據的上面的。

看到remove_if()實際上是根據條件對迭代地址進行了修改,在數據的後面存在一些殘餘的數據,
那些需要刪除的數據。剩下的數據的位置可能不是原來的數據,但他們是不知道的。
調用erase()來刪除那些殘餘的數據。
注意上面例子中通過erase()刪除remove_if()的結果和vs.enc()範圍的數據。

修改自51CTO

大家如果對編程感興趣,想了解更多的編程知識,解決編程問題,諮詢編程學習,可以關注程式設計師互動聯盟(coder_online),QQ群(新手群:451232132,老鳥群:254241126),大牛在線為您提供技術支持。這裡有java高手、C++/C高手、windows/Linux高手等你來。

相關焦點

  • C++ vector詳解
    可以簡單的認為,vector是一個能夠存放任意類型的動態數組。接下來,請跟隨小編一起來複習一下吧。以下是正文前言本文mark了vector的一些接口,介紹了vector中的對內存和對象的管理詳解請見cppreference-vector。
  • C++ vector 使用注意事項
    (給CPP開發者加星標,提升C/C++技能)www.cnblogs.com/leehm/p/10929756.html1、初始化c++, size=end-start, capacity=finish-start很多時候在使用vector的時候,會看到size=capacity,這個時候直接添加元素到尾部,內存明顯是不夠的,此時會重新在別處分配一塊大小足夠有時候也有size<capacity, 這個時候就直接加在尾部了。
  • C++打怪 之 vector
    簡介❝Vector類 是在 java 中可以實現自動增長的對象數組,vector在C++標準模板庫中的部分內容,它是一個多功能的,能夠操作多種數據結構和算法的模板類和函數庫。---百度百科❞2. 場景實例在C語言編程中,涉及到聲明一個全局數組的時候,經常會遇到一種情況,數組的大小設定多少合適。
  • 【C++概念】---vector用法
    在c++中,vector是一個十分有用的容器,下面對這個容器做一下總結。
  • C++ initializer_list 詳解
    ,用於可讓我們列表初始化容器,自定義的函數,自定義的類中的構造函數,要在代碼中使用initializer_list必須包含頭文件initializer_list,這個模板很簡單,包含成員函數 begin(),end(),size(),可以使用這些函數去遍歷列表元素。
  • C++ vector用法詳解
    vector概述  vector是種容器,類似數組一樣,但它的size可以動態改變。  vector的元素在內存中連續排列,這一點跟數組一樣。這意味著我們元素的索引將非常快,而且也可以通過指針的偏移來獲取vector中的元素。
  • python+C、C++混合編程的應用
    有的語言專注於簡單高效,比如python,內建的list,dict結構比c/c++易用太多,但同樣為了安全、易用,語言也犧牲了部分性能。在有些領域,比如通信,性能很關鍵,但並不意味這個領域的coder只能苦苦掙扎於c/c++的陷阱中,比如可以使用多種語言混合編程。
  • C++ vector使用實例
    C++ vector使用實例
  • 詳解C++中的vector 利用swap去除多餘容量
    在使用C++中的 vector的時候,vector的申請的內存不會自動釋放,當 push_back的時候,如果 vector的當前內存不夠使用的時候,vector會自動的二倍增長內存,可能會導致最後內存不斷的增多。下面我們介紹幾種避免這種情況的技巧。
  • C++之旅-vector
    編譯器根據模板創建類型或函數的過程稱為實例化,當使用模板時,需要指出編譯器應把類或函數實例化成何種類型。特別注意,不能使用下標形式添加元素,例如:v[2] = 10;因為添加之前,不存在下標為2的元素。下標運算符只能用於訪問已經存在的元素。迭代器所有的標準容器都可以使用迭代器。
  • C++之vector知多少?
    🕸 為什麼叫vector ?相信很多同學在學習C++語言STL(標準模板庫)中的 vector 的時候有過類似的疑問:vector 不是向量嗎?為什麼會起這個名字?int_vec.push_back(i);}// 加入不確定個數的元素vector<string> str_vec;string word;while (cin >> word) {    str_vec.push_back(word);}在信息學競賽中使用
  • json for modern c++的使用
    很多高級語言如python等都對json有良好的支持,方便程式設計師的使用。然而C++對json沒有很好的內置支持,因此往往要引用一些第三方庫。而網上很多json的包,形形色色種類繁多,但是要麼功能不夠強大,要麼難以使用。
  • C++逆向學習(二) vector
    現在的逆向C++題越來越多,經常上來就是一堆容器、標準模板庫,這個系列主要記錄這些方面的逆向學習心得本文主要介紹std::vector,因為逆向題中的C++代碼可能會故意寫的很繞,比如輸入一個數組,直接給vector賦值即可,但是也可以用稍微費解的方法連續push_back(),也算是一種混淆的手段,文章中的示例會逆向一些故意寫的繁瑣的程序vector內存布局
  • C++ 高階操作:模板元編程
    C++模板給C++提供了元編程的能力,但大部分用戶對 C++ 模板的使用並不是很頻繁,大致限於泛型編程,在一些系統級的代碼,尤其是對通用性、性能要求極高的基礎庫(如 STL、Boost)幾乎不可避免在大量地使用 C++ 模板以及模板元編程。
  • ​跟我學C++中級篇——STL的容器vector
    二、源碼std:vector的源碼很容易找到,其實你看它代碼也不複雜,之所以看上去眼花繚亂的原因不是因為他複雜,而是為了兼容和安全性搞了好多新功能和方法,再加上一些模板本身的技巧。這些都可以暫時忽略過去,重點看重點的相關的函數方法的實現。向量的構造函數其實就是兩部分模板類型名稱和分配器,而分配器一般使用默認的分析器類型,這個回頭再分配器中再詳細分析。
  • C vector詳解
    可以簡單的認為,vector是一個能夠存放任意類型的動態數組。接下來,請跟隨小編一起來複習一下吧。以下是正文前言本文mark了vector的一些接口,介紹了vector中的對內存和對象的管理詳解請見cppreference-vector。
  • C++隨機排序容器中的元素
    作者:apocelipes連結:https://www.cnblogs.com/apocelipes/p/10351335.html在各種程序語言中都提供了將容器元素隨機排序的shuffle方法,c++也不例外。
  • 還不懂c++vector的用法,你憑什麼勇氣來的!
    今天給大家帶來一篇c++vector的介紹,難以置信這篇文章寫了我三天,不過總算整理完畢,現在分享給大家。模板類vector 和 array是數組的替代品。模板類vector 類似於string類,也是一種動態數組。 在 c++ 中,vector 是一個十分有用的容器。
  • 如何正確通過 C++ Primer 學習 C++?
    連結 | https://www.zhihu.com/question/32087709即將讀研,雖然考的是本專業(GIS),但是研究生讀的專業在計算機學院
  • C++ 的門門道道 | 技術頭條 - CSDN
    作者 | 我不想種地責編 | 郭芮C++是一門被廣泛使用的系統級程式語言,更是高性能後端標準開發語言;C++雖功能強大,靈活巧妙,但卻屬於易學難精的專家型語言,不僅新手難以駕馭,就是老司機也容易掉進各種陷阱。