C++基礎: vector 容器及其遍歷與越界問題

主要參考: 遍歷的幾種方式及性能對比; 一個非常隱蔽的越界錯誤



vector類稱作向量類, 它實現了動態的數組, 用於元素數量變化的對象數組. 索引下標從0開始, 元素個數可以動態變化.

構造函數與初始化

  • vector() 空向量
  • vector(int nSize) 聲明元素個數
  • vector(int nSize, const T& t) 聲明元素個數, 且值均爲t。
  • vector<T> a 聲明元素類型爲模板類T
  • vector(const vector&) 複製構造函數。
vector<int> a;
vector<int> a(5);
vector<int> a(5, 0);
vector<int> b(a);

增加與刪除函數

  • a.push_back(const T& t)) 末尾追加元素
  • a.pop_back() 刪除末尾元素
  • a.clear() 清空所有元素
  • a.inset 插入
  • a.erase 刪除
a.push_back(10);
a.push_back(20);
a.push_back(30);    // [10, 20, 30]

a.pop_back();       // [10, 20]

auto index1 = find(a.begin(), a.end(), 20);
a.insert(index1, 0); // [10, 0, 20]

vector<int> ::iterator index2 = find(a.begin(), a.end(), 20);
a.erase(index2);     // [10, 0]

a.clear();

索引與遍歷

  • a.at(int index) 索引index位置(引用)
  • a.front() 首元素的引用
  • a.back() 尾元素的引用
  • a.begin() 指向首元素的指針
  • a.end() 指向末尾的指針, 並不是尾元素
  • a.rbegin() 反向迭代器的起始指針
  • a.rend() 反向迭代器的終止指針

索引

vector<int> a(3, 0);            // [0, 0, 0]

a.front() = 10;
a.at(1) = 20;
a.back() = 30;                  // [10, 20, 30]

迭代器遍歷

  • 正向:
auto iter1 = a.begin();
while(iter1 != a.end())
{
    *iter1 += 1;
    cout << *iter1 << ", ";     // [11, 21, 31]
    iter1++;
}
cout << endl;
  • 反向:
auto iter2 = a.rbegin();
while(iter2 != a.rend())
{
    *iter2 += 1;
    cout << *iter2 << ", ";     // [32, 22, 12]
    iter2++;
}
cout << endl;

下標遍歷

for(int i = 0; i < a.size(); i++)
{
    a[i] += 1;
    cout << a[i] << ", ";       // [13, 23, 33]
}
cout << endl;

auto 輸出

for(auto x : a)
{
    cout << x << ", ";          // [13, 23, 33], 對源數據無影響
}
cout << endl;

注: 三種遍歷方法的Release實時運行差別很小, 同樣高效. 點擊訪問參考博文

其他函數

  • a.empty() 判斷是否爲空
  • a.size() 返回元素的個數
  • a.capacity() 返回預分配內存中所能容納的最多元素數 點擊訪問參考博文
  • a.max_size() 返回所能容納的最多元素數
vector<int> a(5);                       
cout << a.size() << endl;           // 5 
cout << a.capacity() << endl;       // 5
cout << a.max_size() << endl;       // 1073741823

vector<int> b;
cout << b.size() << endl;           // 0
cout << b.capacity() << endl;       // 0
cout << b.max_size() << endl;       // 1073741823

越界問題

在這裏插入圖片描述

  • 下標越界,如本例的 a[5], 但程序Debug報錯, Release不報錯, 輸出該地址中存儲值. 點擊訪問參考博文
  • 隱蔽型越界, 如以下代碼. 當size=0時, 減一操作是危險的. 因爲a.size()是無符號整數,根據C++的規則表達式a.size()-1也是個無符號整數,而-1轉成無符號數的值是4294967295, 顯然越界, 應該避免使用a.size()-1. Java等語言沒有無符號類型, 也就避免了這一問題. 點擊訪問參考博文
vector<int> a;
for(int i = 0; i <= a.size() - 1; i++)
{
    cout << a[i] << endl;
}

其他問題

  • static索引變量問題:
    在這裏插入圖片描述
    如圖所示, 由於static變量只初始化一次, 有固定內存, 相當於全局變量, 所以並不能按照意圖在每次調用函數時都被賦值爲3, 只會在反覆++, 最後造成越界. 應該改正爲:
static int index;
index = 3;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章