初識 vector
标準庫類型
vector
表示類型相同的對象的集合,因之可以容納其他對象,也被稱作容器(container)。引用不是對象,是以不存在引用的 vector 。
同 string 一樣,vector 也是對數組的某種抽象。
初始化
vector 是C++ 的一個類模闆而非類型,編譯器根據模闆建立類或者函數的過程稱為執行個體化,是以由 vector 生成的類型必須包含 vector 中元素的類型:
vector<int> ivec; // 包含元素類型為int
vector<vector<string>> file; // 包含元素類型為 vector<string>
vector 對象常用的初始化方法:
vector<T> v1; // vector 的元素類型為 T,元素執行預設初始化
// 這是最常見的方式
vector<T> v2(v1); // v2 中包含 v1 中所有元素的副本,
// v2 和 v1 的元素類型必須相同
vector<T> v3 = v2; // 等價與 vector<T> v3(v2)
vector<T> v4(n, val); // v4 包含 n 個元素,每個元素的值為 val
vector<T> v5(n); // v5 包含了 n 個執行了 值初始化 的元素
vector<T> v6{a, b, c, d}; // v6 包含了初始值個數的元素,這裡是 4,
// 每個元素的的值被賦予相應的初始值
vector<T> v7 = {a, b, c, d}; // 等價于 vector<T> v7{a, b, c, d}
值初始化發生在隻提供 vector 對象容納的元素數量而略去初始值的時候,庫會根據元素類型來決定賦給元素的初值,如果 vector 中元素是内置類型,則元素初始值自動設為 0 ;如果是類類型,則由類預設初始化。
值初始化的兩個特殊限制:1. 對于要求明确提供初始值的類,必須提供初始的元素值,否則無法完成初始化工作;2. 隻提供了元素數量而沒有設定初始值,隻能使用直接初始化。
// 下面操作将引發錯誤
// error: conversion from ‘int’ to non-scalar type
// ‘std::vector<int>’ requested
vector<int> v1 = 10;
vector 對象的操作
函數 | 效果 |
---|---|
v.empty() | v 為空的時候傳回真;否則為假 |
v.size() | 傳回 v 中元素的個數 |
v.push_back(t) | 在 v 的尾端添加一個值為 t 的元素 |
v[n] | 傳回 v 中第 n 個位置上元素的引用 |
v1 = v2 | 用 v2 中元素的拷貝替換 v1 中的元素 |
v1 = {a, b, c} | 用清單中的元素的拷貝替換 v1 中的元素 |
v1 == v2 | v1 和 v2 相等當且僅當它們的元素數量相同且對應位置的元素值都相同 |
v1 != v2 | 同上 |
<, <=, >, >= | 以字典順序進行比較 |
最常見的情況是,建立了一個空的 vector,然後使用成員函數
push_back()
向 vector 的尾部添加元素。
// 建立一個 vector 對象,包含 100 個類型為 int 的元素
// 元素的值從 1 ~ 100
vector<int> ivec;
for (int i = 0; i != 100; ++i) {
ivec.push_buck(i);
}
可以通過下标通路 vector 中的元素:
// 對于上面的 ivec
cout << ivec[4] << endl; // 輸出 5
類似 string,vector 的下标起始于 0,類型為 size_type,由 vector 定義,同 vector 對象的聲明一樣,使用 size_type 必須指定它的類型:
vector<int>::size_type i; // OK
// 下面操作将引發錯誤
// error: ‘template<class _Tp, class _Alloc> class std::vector’
// used without template parameters
vector::size_type i2;
下标的合法範圍在 0 到 size() - 1 之間,size() 函數傳回 vector 對象中元素的個數,類型為 size_type,不能通過下标形式添加元素:
// 編譯器不負責檢測下标的合法性
// 編譯通過,但在運作是引發錯誤
// 緩沖區溢出
vector<int> ivec;
ivec[0] = 4; // error
兩個練習:
練習 3.16: 從 cin 讀入一組詞,并把它們存入一個 vector 對象,然後設法把所有詞都改寫為大寫形式。輸出改變後的結果,每個詞占一行。
// toup.cc
// P94 exercise 3.17
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<string> sver;
string temp;
// use 'Ctrl-D' to send an EOF character
while (cin >> temp) {
if (temp == "\n")
break;
sver.push_back(temp);
}
for (auto &str : sver) { // string &str
for (auto &c : str) { // char &c
c = toupper(c);
}
}
for (int i = 0; i != sver.size(); ++i) {
cout << sver[i] << endl;
}
return 0;
}
$ ./toup.out
when you are old and grey and full of sleep
WHEN
YOU
ARE
OLD
AND
GREY
AND
FULL
OF
SLEEP
練習 3. 20: 讀入一組整數,并把它們存入一個 vector 對象,将每對相鄰整數的和輸出。改寫程式,要求輸出第一個和最後一個元素的和,接着輸出第二個和倒數第二個元素的和,以此類推。
// add.cc
// P94 exercise 3.20
#include <iostream>
#include <vector>
// 通過類型别名避免多次聲明複雜的類型
using type = std::vector<int>::size_type;
int main(){
std::vector<int> ivec;
int temp;
while(std::cin >> temp) {
ivec.push_back(temp);
}
type size = ivec.size();
std::cout << "Size of ivec : " << size << std::endl << std::endl;
// 列印相鄰元素的和
for(type i = 0; i != size - 1; ++i) {
std::cout << "ivec[" << i << "] + ivec["
<< i + 1 << "] = "
<< ivec[i] + ivec[i+1]
<< std::endl;
}
std::cout << std::endl;
// 列印首尾對稱位置的和
// decltype() 傳回變量的類型
// 這裡 i 的類型是 vector<int>::size_type
for(decltype(size) i = 0; i != size / 2 + 1; ++i) {
std::cout << "ivec[" << i << "] + ivec["
<< size - i - 1 << "] = "
<< ivec[i] + ivec[size - i - 1]
<< std::endl;
}
return 0;
}
$ ./add.out
11 22 33 44 55 66 77 88 99
E
Size of ivec : 9
ivec[0] + ivec[1] = 33
ivec[1] + ivec[2] = 55
ivec[2] + ivec[3] = 77
ivec[3] + ivec[4] = 99
ivec[4] + ivec[5] = 121
ivec[5] + ivec[6] = 143
ivec[6] + ivec[7] = 165
ivec[7] + ivec[8] = 187
ivec[0] + ivec[8] = 110
ivec[1] + ivec[7] = 110
ivec[2] + ivec[6] = 110
ivec[3] + ivec[5] = 110
ivec[4] + ivec[4] = 110
好好學習天天向上~~╭(●`∀´●)╯ ヾ(*´▽‘*)ノ ~~