vector常用操作
1.前言
昨晚在家,心血来潮想了解下vector,所以翻cppreference看了看,今天便小小总结下
2.常用函数的思维导图
这是我把cppreference中我常用的摘录下来做成的思维导图,更清晰一点
2.1迭代器
迭代器是什么? 简单理解:提供遍历访问的一种方式 官方理解:是一个对象,可以循环访问C++标准库容器中的元素,并提供对各个元素的访问
cbegin的c代表的是返回const,所以他不能修改数据 rbegin的r代表反向第一个
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
int main()
{
std::vector<int> v = { 0,1,2,3,4,5 };
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
for (auto it = v.rbegin(); it < v.rend(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
for (auto it = v.cbegin(); it < v.cend(); it++)
{
std::cout << *it << " ";
// *it = 1; 错误
}
std::cout << std::endl;
for (auto it = v.crbegin(); it < v.crend(); it++)
{
std::cout << *it << " ";
// *it = 1; 错误
}
}
输出
1
2
3
4
0 1 2 3 4 5
5 4 3 2 1 0
0 1 2 3 4 5
5 4 3 2 1 0
2.2容量
size:现在容器中有多少个元素
resize:当新分的内存比现在内存大时,后面新扩充的内存部分,都会用默认元素来填充,所以capacity(内存)也变大;没现在内存大时,原来内存中的元素多的元素会被删除,但是capacity不变
capacity:你分配了多少的内存,即使你里面元素减少了,但是内存也不会减少
shrink_to_fit:把多余的内存给删掉,比如元素4个,内存有5,则把多余的一个内存给干掉,注意这个函数没有返回值
reserve:是内存预留空间,但是没有给新开的内存初始化,只是说明可以利用它,但是不能有效访问空间,因为现在里面什么都没,所以元素个数其实没变。如果预留空间大于当前capacity空间则会重新分配内存 reserve:并不会删除或者添加元素,也不会改变元素的数量 reserve:这个函数设计的是只能用来增加capacity,不能用来减少capacity,传入的参数小于或等于当前的capacity,reserve函数不会做任何事情,所以capacity保持不变
v[5]:这样通过索引的只能访问已存在的元素,否则就访问越界
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
std::vector<int> v;
std::cout << "size:" << v.size() << std::endl;
// 0
v = { 1,2,3,4,5 };
std::cout << "size:" << v.size() << std::endl;
// 5
v = { 1,2,3,4 };
std::cout << "size:" << v.size() << std::endl;
// 4 元素为4个
std::cout << "capacity:" << v.capacity() << std::endl;
// 5 内存为5个空间大小
v.shrink_to_fit();
std::cout << "capacity:" << v.capacity() << std::endl;
// 4
v.resize(10);
std::cout << "capacity:" << v.capacity() << std::endl;
// 10
std::cout << "v[5]:" << v[5] << std::endl;
// 0 因为resize新增空间时,用默认数据来填充新增加的空间
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 1 2 3 4 0 0 0 0 0 0
v.resize(3);
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 1 2 3
std::cout << "capacity:" << v.capacity() << std::endl;
// 10
v.shrink_to_fit();
std::cout << "capacity:" << v.capacity() << std::endl;
// 3
v.reserve(9);
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 1 2 3
std::cout << "capacity:" << v.capacity() << std::endl;
// 9
std::cout << "v[5]:" << v[5] << std::endl;
// 6619252 随机地址,因为reserve分配的空间还没有初始化,但是resize分配的时候也就初始化了,所以上面的v[5]是0
// 但其实这样访问是错误的v[5]这是通过[]操作符索引来访问的,但是索引访问只能访问已存在的元素,而此时已存在的元素只有1 2 3
// 这就是访问越界,因为v里面只有3个元素,5超过了有效范围
v.reserve(2);
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 1 2 3
std::cout << "capacity:" << v.capacity() << std::endl;
// 9 因为reserve(2) 2小于9,所以什么都不做
2.3元素访问
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
std::vector<int> v = { 0,1,2,3,4,5,6 };
v.resize(3);
std::cout << "capacity:" << v.capacity() << std::endl;
// 7
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 0 1 2
std::cout << "v[6]:" << v[6] << std::endl;
// 6
//std::cout << v.at(3) << std::endl;
// 代码会报错,因为at里面会检查是否访问的超过了size,也就是有效元素的范围
// 而operator[]则没有这个检查
std::cout << "v.at(2):" << v.at(2) << std::endl;
// 2
std::cout << "v.front():" << v.front() << std::endl;
// 0
std::cout << "v.back():" << v.back() << std::endl;
// 2
resize(3)执行后,应该元素里面就剩下0,1,2了,为什么v[6]还能访问呢
这和resize和迭代器工作方式有关,当调用v.resize(3);后,v的大小(size)变为3,但是capacity可能仍然保持不变。这意味着,虽然你删除了一些元素,但是这些元素占用的内存并没有被释放。因此,当你访问v[6]时,你可能仍然能够看到原来的值,因为那块内存尚未被覆盖。然而,这是非常危险的,因为这是未定义的行为。
另一方面,当你使用迭代器遍历v时,迭代器只会访问v的有效元素,也就是说,只会访问v的大小(size)范围内的元素。因此,当你执行for (auto it = v.begin(); it < v.end(); it++)时,你只会看到v的前三个元素,即0,1,2,而不会看到6,因为6已经不再v的大小范围内了。
所以,[]操作符和*it都是读取内存的值,但是他们访问的范围是不同的。[]操作符可以访问到任何位置的内存,包括超出v的大小范围的内存,而*it只能访问到v的大小范围内的内存。
2.4修改数据
assign会清除容器里以前的内容,当输入的元素比原来的容量空间小时,则原来容量空间不变 emplace替代insert emplace_back替代push_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
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
std::vector<int> v = { 0,1,2,3,4,5,6 };
v.assign(4, 3);
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
// 3 3 3 3
std::cout << std::endl;
std::cout << "v.capacity():" << v.capacity() << std::endl;
// 7
v.pop_back();
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 3 3 3
v = { 0,1,2,3,4,5,6 };
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 0 1 2 3 4 5 6
v.insert(v.begin(), -1);
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// -1 0 1 2 3 4 5 6
v.insert(v.begin() + 3, 2, 999);
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// -1 0 1 999 999 2 3 4 5 6
std::vector<int> v1 = { 11,11,11 };
v.insert(v.begin(), v1.begin(), v1.end());
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 11 11 11 -1 0 1 999 999 2 3 4 5 6
v.erase(v.begin());
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 11 11 -1 0 1 999 999 2 3 4 5 6
// 左开右闭
v.erase(v.begin(), v.begin() + 2);
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// -1 0 1 999 999 2 3 4 5 6
v.erase(v.begin() + 3, v.begin() + 5);
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// -1 0 1 2 3 4 5 6
v.clear();
std::cout << "capacity:" << v.capacity() << std::endl;
//v.at(0); 会报错
v = { 1,2,3,4,5 };
v1 = { 6,7 };
std::cout << "v1:";
for (auto it = v1.begin(); it < v1.end(); it++)
{
std::cout << * it << " ";
}
// 6 7
std::cout << "v1.capacity:" << v1.capacity() << std::endl;
// 3 因为之前v1是3个元素,现在是2个元素
v.swap(v1);
std::cout << "v.swap after:";
for (auto it = v.begin(); it < v.end(); it++)
{
std::cout << *it << " ";
}
// 6 7
std::cout << "v.swap after's capacity:" << v.capacity() << std::endl;
// 3 因为v1内存空间是3
std::cout << std::endl;
for (auto it = v1.begin(); it < v1.end(); it++)
{
std::cout << *it << " ";
}
// 1 2 3 4 5
std::cout << "v1.capacity:" << v1.capacity() << std::endl;
// 15
std::cout << std::endl;
v1.emplace(v1.begin(), 0);
for (auto it = v1.begin(); it < v1.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 0 1 2 3 4 5
v1.emplace_back(6);
for (auto it = v1.begin(); it < v1.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;