如果一个类存在的意义是为了保存对象,那么就称它为容器(container)。
换句话说,容器是用来保存一堆指定类型对象的集合。
构建程序的重要步骤就是选择一个合适的容器来保存处理任务的数据(该容器本身也能提供一些用于处理数据的有用方法)。
vector 是最有用的容器,它其实就是一个动态的数组,可以根据需要自动调整大小,其中保存的元素在内存中的存储方式是连续的,类似 Java 中的 ArrayList。
通常,使用 vector 是最好的选择,除非你有很好的理由选择其他容器。
《C++ Primer》,第五版
vector 的初始化
默认初始化
vector<int> v;
调用默认构造函数,创建一个空的 vector。
指定容量的初始化
vector<int> v(10);
创建一个能容纳 10 个元素(这里是 int 类型)的 vector。
元素的默认值为类型的初始值,指针的默认值为 nullptr,整数的默认值为 0。
指定容量和初始值的初始化
vector<int> v(10, 100);
创建一个能容纳 10 个 int 类型元素的 vector,其中每个元素的默认值为 100。
列表初始化
vector<int> v = {1, 2, 3, 4, 5};
创建包含指定元素的 vector。
拷贝初始化
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2(v1);
通过拷贝构造函数克隆一个旧的 vector 来初始化新的 vector。
拷贝方式是深拷贝,即新的 vector 是独立的副本,对新的 vector 中元素的操作并不会反映到旧的 vector 上。
访问 vector 中的元素
下标运算符
使用下标运算符访问指定位置的元素:
vector<int> v = {1, 2, 3, 4, 5};
cout << v[2] << endl; // 输出 3
也可以使用下标运算符来修改某个位置的元素:
vector<int> v = {1, 2, 3, 4, 5};
v[2] = 100;
cout << v[2] << endl; // 输出 100
使用下标运算符去访问元素是不进行索引越界检查的,也就是说可以传入一个明显比实际容量大的索引,而且这样做也不会产生错误,这样读取的值是不确定的。
vector<int> v = {1, 2, 3, 4, 5};
cout << v[2] << endl; // 输出 3
cout << v[200] << endl; // 输出 0
因此用随后介绍的 at() 方法去访问元素会比较安全。
at() 方法
vector<int> v = {1, 2, 3, 4, 5};
cout << v.at(2) << endl; // 输出 3
cout << v.at(200) << endl; // 抛异常
at() 方法会在访问索引越界的时候抛出一个 out_of_range 异常。
常见的索引 for 循环
vector<int> v = {1, 2, 3, 4, 5};
for (int i = 0; i < v.size(); i++) {
cout << v[i] << endl; // 输出 1 ~ 5
}
范围 for 循环
vector<int> v = {1, 2, 3, 4, 5};
for (int v_: v) {
cout << v_ << endl; // 输出 1 ~ 5
}
使用范围 for 循环去遍历 vector 中保存的元素。
范围 for 循环的语法比索引 for 循环更简洁,而且还能避免发生越界访问。
可以把 v_ 的类型设置为 auto,让编译器自动推导元素的类型,减少了手动指定类型的麻烦,在类型名很长的情况下特别有用。
for (auto v_ : v) {
cout << v_ << endl;
}
默认的范围 for 循环是将容器 v 中的每个元素拷贝到变量 v_ 中,由于是值拷贝,所以对 v_ 的修改并不会反映到原本的容器中的元素上。
使用引用访问元素,就可以对原本容器中的元素进行修改:
vector<int> v = {1, 2, 3, 4, 5};
for (auto& v_ : v) {
v_ += 1; // 把每个数 + 1
}
for (auto v_ : v) {
cout << v_ << endl; // 输出 2、3、4、5、6
}
这样做还有个好处:避免不必要的拷贝,特别是在遍历处理很大的对象时,可以提升程序性能。
如果只想避免耗时的拷贝,而不想修改原本的元素,加 const。
for (const auto& v_ : v) {
cout << v_ << endl;
}
使用 front() 方法和 back() 方法
vector<int> v = {1, 2, 3, 4, 5};
cout << v.front() << endl; // 输出 1
cout << v.back() << endl; // 输出 5
front() 方法返回 vector 中的第一个元素。
back() 方法返回 vector 中的最后一个元素。
使用 begin() 和 end() 方法
这两个方法返回的是迭代器。
用于和 for 循环配合使用,遍历容器中的元素。
很多函数如 insert()、erase() 都需要指定位置,通常 begin() 和 end() 会用来标识某个位置。
标准库算法如 sort() 和 find(),要求传入 begin() 和 end() 迭代器,以指定操作的范围。
begin() 方法返回指向 vector 中第一个元素的迭代器。
end() 方法返回指向 vector 尾部元素之后一个位置的迭代器(比最后一个元素再后一位)。
vector<int> v = {1, 2, 3, 4, 5};
for (auto it = v.begin(); it < v.end(); ++it) {
cout << *it << endl; // 输出 1、2、3、4、5
}
begin() 指向的是头元素,所以可以通过 ***** 来获取头元素的值,但是 end() 方法并不指向有效的元素,所以不能通过 ***** 来获取值。
往 vector 中添加元素
push_back() 方法
vector<int> v = {1, 2, 3, 4, 5};
v.push_back(6);
for (int v_ : v) {
cout << v_ << endl; // 输出 1、2、3、4、5、6
}
往 vector 的末尾追加一个元素。
insert() 方法
在 vector 的指定位置插入一个或多个元素。
插入单个元素:
vector<int> v = {1, 2, 3, 4, 5};
v.insert(v.begin() + 2, 10);
for (int v_ : v) {
cout << v_ << endl; // 输出 1、2、10、3、4、5
}
该方法接收的参数是迭代器,而不是索引!
插入多个元素:
vector<int> v = {1, 5};
v.insert(v.begin() + 1, {2, 3, 4});
for (int v_ : v) {
cout << v_ << endl; // 输出 1、2、3、4、5
}
在指定位置插入新添加的元素之后,会将原位置上的元素及其之后的所有元素全部向后移动,尽量不要在数组中间频繁地插值。
assign() 方法
用法一:先将当前的 vector 清空,并批量插入多个相同的元素。
vector<int> v = {1, 2, 3, 4, 5};
cout << v.size() << endl; // 输出 5
v.assign(3, 100); // 插入 3 个 100
cout << v.size() << endl; // 输出 3
for (int v_ : v) {
cout << v_ << " "; // 输出 100、100、100、100、100
}
用法二:使用另一个 vector 指定范围内的元素来替换当前 vector 中所有的元素。
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {6 ,5, 4, 3, 2, 1};
v2.assign(v1.begin() + 1, v1.end() - 1); // 取 2、3、4 赋值给 v2
for (int v_ : v2) {
cout << v_ << endl; // 输出 2、3、4
}
v2 中原有的元素都被清除了,然后才赋值新的元素。
删除 vector 中的元素
pop_back() 方法
vector<int> v = {1, 2, 3, 4, 5};
v.pop_back();
for (int v_ : v) {
cout << v_ << endl; // 输出 1、2、3、4
}
删除 vector 末尾的元素。
该函数的返回值是 void,被删除的元素不会返回。
clear() 方法
vector<int> v = {1, 2, 3, 4, 5};
v.clear();
cout << v.capacity() << endl; // 输出 5
cout << v.size() << endl; // 输出 0
用于清空 vector,删除保存的所有元素,使 vector 的大小变为 0,但并不改变最大容量。
erase() 方法
用于删除指定位置的一个元素或指定范围内的全部元素。
删除单个元素:
vector<int> v = {1, 2, 3, 4, 5};
v.erase(v.begin()); // 删除头元素
for (int v_ : v) {
cout << v_ << endl; // 输出 2、3、4、5
}
注意:erase() 方法接受的参数不是索引,也不是值,而是迭代器。
删除指定位置的元素后,后面的元素会往前移动。
删除一个连续范围内的全部元素:
vector<int> v = {1, 2, 3, 4, 5};
v.erase(v.begin(), v.begin() + 3); // 删除前三个元素
for (int v_ : v) {
cout << v_ << endl; // 输出 4、5
}
删除范围时,使用的是半开区间 [first, last),包含头,不包含尾,即删除 first 到 last - 1 之间的元素。
调整容量的方法
reserve() 方法
vector<int> v;
v.reserve(5); // 预先为 5 个元素分配内存空间
cout << v.capacity() << endl; // 输出 5
cout << v.size() << endl; // 输出 0
预先分配指定数量的存储空间,避免在添加元素时频繁的重新分配内存。
这只改变 vector 的最大容量,并不添加新的元素。
注意:使用 reserve() 方法之后,相当于新开了一块内存空间,然后把原来的那一堆值全部拷贝过去,原来的那块内存空间将被回收,若此时继续使用指向原来那块内存空间地址的指针,获取的值是随机的,而且还不会报错。
vector<int> v = {1, 2, 3, 4, 5};
int *ptr = &v[0];
cout << *ptr << endl; // 1
v.reserve(10);
cout << *ptr << endl; // 输出不可预知的值
resize() 方法
vector<int> v = {1, 2, 3, 4, 5};
v.resize(3);
cout << v.capacity() << endl; // 输出 5
cout << v.size() << endl; // 输出 3
for (int v_ : v) {
cout << v_ << endl; // 输出 1、2、3
}
调整 vector 的元素数量。如果新的 size 比当前的 size 大,vector 会添加新元素,如果容量不够,则执行扩容的操作,新增的元素将用默认值填充(例如 int 类型的默认值为 0)。
如果想指定新增元素的默认值,则使用:
v.resize(10, 100); // 会将新增的元素填充为 100。
如果新的 size 比当前的 size 小,vector 中的多余元素将会被移除,但最大容量不会发生变化。
shrink_to_fit() 方法
请求缩减 vector 的容量(capacity)以适应当前的大小(size),减少内存的浪费。
容量是容器最多可以存储的元素数量,而大小是实际存储的元素数量。当 vector 扩容时,容量会增加;但移除元素后,容量不会自动减少,这就导致了内存的浪费。
vector<int> v = {1, 2, 3, 4, 5};
cout << v.capacity() << endl; // 输出 5
v.resize(3); // 将 size 缩减为 3,但容量保持不变
cout << v.capacity() << endl; // 输出 5
v.shrink_to_fit(); // 请求释放多余的容量
cout << v.capacity() << endl; // 输出 3
注意这只是请求,实际缩不缩还得看编译器心情。
其它有用的方法
empty() 方法
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2;
cout << v1.empty() << endl; // 输出 0
cout << v2.empty() << endl; // 输出 1
检查 vector 是否为空。
size() 方法
vector<int> v = {1, 2, 3, 4, 5};
cout << v.size() << endl; // 输出 5
返回当前 vector 中保存了多少个元素。
capacity() 方法
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2(30);
vector<int> v3;
cout << v1.capacity() << endl; // 输出 5
cout << v2.capacity() << endl; // 输出 30
cout << v3.capacity() << endl; // 输出 0
返回当前 vector 最多可以存储多少个元素。
swap() 方法
vector<int> v1 = {1, 2, 3};
vector<int> v2 = {4, 5, 6};
v1.swap(v2); // 交换 v1 和 v2 的内容
for (int num : v1) {
cout << num << " "; // 输出 4、5、6
}
cout << endl;
for (int num : v2) {
cout << num << " "; // 输出 1、2、3
}
交换两个 vector 中保存的元素。
标签:容器,begin,cout,int,元素,vector,方法,入门 From: https://blog.csdn.net/Slade_XiaoZe/article/details/142360085