3.2、vector容器
声明:本文是在学习C++ STL–标准模板库的笔记,方便以后复习;主要参考《C++ Prime》、《C++标准库》、《黑马程序员匠心之作|C++教程从0到1入门编程》等。
3.2.1、 vector基本概念
功能:
- vector数据结构和数组非常相似,也称为单端数组
vector与普通数组区别:
- 不同之处在于数组是静态空间,而vector可以动态扩展
动态扩展:
- 并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
- vector容器的迭代器是支持随机访问的迭代器
使用vector前,必须包含头文件#include <vector>
;
3.2.2、 vector构造函数
功能描述:
函数原型:
vector<T> v;
//采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());
//将v[begin(), end())区间中的元素拷贝给本身。
vector(n, elem);
//构造函数将n个elem拷贝给本身。
vector(const vector &vec);
//拷贝构造函数。
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <iostream> #include <vector> using namespace std;
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; }
void test01() { vector<int> v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1);
vector<int> v2(v1.begin(), v1.end()); printVector(v2);
vector<int> v3(10, 100); printVector(v3); vector<int> v4(v3); printVector(v4); }
int main() {
test01();
system("pause");
return 0; }
|
输出:
1 2 3 4
| 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
|
3.2.3、 vector赋值操作
功能描述:
函数原型:
vector& operator=(const vector &vec);
//重载等号操作符
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);
//将n个elem拷贝赋值给本身。
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <iostream> #include <vector> using namespace std;
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; }
void test01() { vector<int> v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1);
vector<int>v2; v2 = v1; printVector(v2);
vector<int>v3; v3.assign(v1.begin(), v1.end()); printVector(v3);
vector<int>v4; v4.assign(10, 100); printVector(v4); }
int main() {
test01();
system("pause");
return 0; }
|
3.2.4、 vector容量和大小
功能描述:
函数原型:
empty();
//判断容器是否为空
capacity();
//容器的容量,一般是2的n次方
size();
//返回容器中元素的个数
resize(int num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
resize(int num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除
vector的capacity很重要
①、一旦内存重新分配,vector元素相关的reference、pointer、iterator都会失效;
②、内存重新分配很消耗时间。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <iostream> #include <vector> using namespace std;
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; }
void test01() { vector<int> v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); if (v1.empty()) { cout << "v1为空" << endl; } else { cout << "v1不为空" << endl; cout << "v1的容量 = " << v1.capacity() << endl; cout << "v1的大小 = " << v1.size() << endl; }
v1.resize(15,10); printVector(v1);
v1.resize(5); printVector(v1); }
int main() {
test01();
system("pause");
return 0; }
|
输出:
1 2 3 4 5 6
| 0 1 2 3 4 5 6 7 8 9 v1不为空 v1的容量 = 16 v1的大小 = 10 0 1 2 3 4 5 6 7 8 9 10 10 10 10 10 0 1 2 3 4
|
这里要注意的是为什么v.capacity是16,因为vector的容量是2的n次方,这里因为vector存了10个数,因此capacity是2的4次方!
总结:
- 判断是否为空 — empty
- 返回元素个数 — size
- 返回容器容量 — capacity
- 重新指定大小 — resize
3.2.5、 vector插入和删除
功能描述:
函数原型:
push_back(ele);
//尾部插入元素ele
pop_back();
//删除最后一个元素
insert(const_iterator pos, ele);
//迭代器指向位置pos插入元素ele
insert(const_iterator pos, int count,ele);
//迭代器指向位置pos插入count个元素ele
erase(const_iterator pos);
//删除迭代器指向的元素
erase(const_iterator start, const_iterator end);
//删除迭代器从start到end之间的元素
clear();
//删除容器中所有元素
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include <iostream> #include <vector> using namespace std;
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; }
void test01() { vector<int> v1; v1.push_back(10); v1.push_back(20); v1.push_back(30); v1.push_back(40); v1.push_back(50); printVector(v1); v1.pop_back(); printVector(v1); v1.insert(v1.begin(), 100); printVector(v1);
v1.insert(v1.begin(), 2, 1000); printVector(v1);
v1.erase(v1.begin()); printVector(v1);
v1.erase(v1.begin(), v1.end()); v1.clear(); printVector(v1); }
int main() {
test01();
system("pause");
return 0; }
|
输出:
1 2 3 4 5
| 10 20 30 40 50 10 20 30 40 100 10 20 30 40 1000 1000 100 10 20 30 40 1000 100 10 20 30 40
|
总结:
- 尾插 — push_back
- 尾删 — pop_back
- 插入 — insert (位置迭代器)
- 删除 — erase (位置迭代器)
- 清空 — clear
3.2.6、 vector数据存取
功能描述:
函数原型:
at(int idx);
//返回索引idx所指的数据
operator[];
//返回索引idx所指的数据
front();
//返回容器中第一个数据元素
back();
//返回容器中最后一个数据元素
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <iostream> #include <vector> using namespace std;
void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); }
for (int i = 0; i < v1.size(); i++) { cout << v1[i] << " "; } cout << endl;
for (int i = 0; i < v1.size(); i++) { cout << v1.at(i) << " "; } cout << endl;
cout << "v1的第一个元素为: " << v1.front() << endl; cout << "v1的最后一个元素为: " << v1.back() << endl; }
int main() {
test01();
system("pause");
return 0; }
|
输出:
1 2 3 4
| 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 v1的第一个元素为: 0 v1的最后一个元素为: 9
|
总结:
- 除了用迭代器获取vector容器中元素,[ ]和at也可以
- front返回容器第一个元素
- back返回容器最后一个元素
3.2.7、 vector互换容器
功能描述:
函数原型:
swap(vec);
// 将vec与本身的元素互换
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
| #include <iostream> #include <vector> using namespace std;
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; }
void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1);
vector<int>v2; for (int i = 10; i > 0; i--) { v2.push_back(i); } printVector(v2);
cout << "互换后" << endl; v1.swap(v2); printVector(v1); printVector(v2); }
void test02() { vector<int> v; for (int i = 0; i < 100000; i++) { v.push_back(i); }
cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl;
v.resize(3);
cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl;
vector<int>(v).swap(v);
cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl; }
int main() {
test01();
test02();
system("pause");
return 0; }#include <vector>
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; }
void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1);
vector<int>v2; for (int i = 10; i > 0; i--) { v2.push_back(i); } printVector(v2);
cout << "互换后" << endl; v1.swap(v2); printVector(v1); printVector(v2); }
void test02() { vector<int> v; for (int i = 0; i < 100000; i++) { v.push_back(i); }
cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl;
v.resize(3);
cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl;
vector<int>(v).swap(v);
cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl; }
int main() {
test01();
test02();
system("pause");
return 0; }
|
输出:
1 2 3 4 5 6 7 8 9 10 11
| 0 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1 互换后 10 9 8 7 6 5 4 3 2 1 0 1 2 3 4 5 6 7 8 9 v的容量为:131072 v的大小为:100000 v的容量为:131072 v的大小为:3 v的容量为:3 v的大小为:3
|
总结:swap可以使两个容器互换,可以达到实用的收缩内存效果
3.2.8、vector预留空间
功能描述:
函数原型:
reserve(int len);
//容器预留len个元素长度,预留位置不初始化,元素不可访问。
注意:
- vector不能使用reserve()缩减容量,调用reserve()所给的实参如果小于当前vector的容量,将会失效。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <vector>
void test01() { vector<int> v;
v.reserve(100000);
int num = 0; int* p = NULL; for (int i = 0; i < 100000; i++) { v.push_back(i); if (p != &v[0]) { p = &v[0]; num++; } }
cout << "num:" << num << endl; }
int main() {
test01(); system("pause");
return 0; }
|
输出:
总结:如果数据量较大,可以一开始利用reserve预留空间
3.2.9、vector容器的能力:
①、vector是将元素复制到dynamic array中,元素之间存在一定的顺序,所以vector是一种有序集合,支持随机访问;
②、在末端增加或删除元素,效率比较高;在前端或中段插入或删除元素效率比较低;
3.2.10、vector异常处理
①、如果push_back()安插元素时发生异常,函数将不产生效用。
②、如果元素的 copy/move 操作(包括构造函数和 assignment 操作符)不抛出异常,那么insert()、emplace()、emplace_back()和push_back()要么成功,要么不产生效用。
③、pop_back()绝不会抛出任何异常。
④、如果元素的copy/move操作(包括构造函数和assignment操作符)不抛出异常,erase()就不抛出异常。
⑤、swap()和clear()不抛出异常。
⑥、如果元素的copy/move操作(包括构造函数和assignment操作符)不抛出异常,那么所有操作不是成功,就是不产生效用。
3.2.10、vector定义二维数组
①、使用vector定义二维数组
1 2
| vector<vector<int> > v; vector<vector<int>> v;
|
②、访问二维vector的元素的三种方式
如果指定外层和内层向量的大小,就可用operator[]进行读和写;如果只指定列向量大小,就能用push_back()函数进行写,不能用operator[]进行读和写。
a、指定vector–列(外层)大小
可用push_back函数进行初始化:
1 2 3
| v.resize(3); v[1].push_back(9); cout<<v[1][0];
|
b、指定vector–行(内层)的大小
提前设定好每行vector的大小,就可用operator[]访问,如下:
1 2 3 4
| for(int i=0;i<m;i++) { array[i].resize(n); }
|
1 2 3 4 5 6 7 8
| vector< vector<int> > a(10); for(int i = 0; i < 10; i++) { for(int j = 0; j < 5; j++) { a[i].push_back(1); } }
|
c、同时制定vector–行列大小
1
| v.resize(n, vector<int>(m));
|
1 2 3 4 5 6 7
| vector<vector<int> > array(4, vector<int>(4)); int arr[4][4] = { {2,4,6,9},{3,5,7,10},{5,7,9,11},{6,8,10,13} }; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) array[i][j] = arr[i][j]; }
|