vector
[vector文档](vector - C++ Reference (cplusplus.com))
vector
是序列容器,表示可以改变大小的数组。要使用vector
,同样需要引入头文件
#include <vector>
vector与string
string
中会有\0
,vector<char>
中不会出现\0
string
可以进行字符串的拼接,vector<char>
不可以
vector的构造
void test1() {
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
cout << "v1:";
for (size_t i = 0; i < v1.size(); ++i) {
cout << v1[i] << " ";
}
cout << endl;
vector<int> v2(v1);
cout << "v2:";
for (size_t i = 0; i < v2.size(); ++i) {
cout << v2[i] << " ";
}
cout << endl;
}
vector的3种遍历方式
operatro[]、迭代器、范围for
void test2() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); //operator[] for (size_t i = 0; i < v.size(); ++i) { cout << v[i] << " "; } cout << endl; //迭代器 vector<int>::iterator it = v.begin(); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; //范围for for (auto x : v) { cout << x << " "; } cout << endl; }
3种类型的迭代器
void test3() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); //正向迭代 可读可写 vector<int>::iterator it = v.begin(); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; //逆向迭代 vector<int>::reverse_iterator rit = v.rbegin(); while (rit != v.rend()) { cout << *rit << " "; ++rit; } cout << endl; } //只读 void print_vector(const vector<int>& v) { vector<int>::const_iterator it = v.begin(); while(it != v.end()) { //*it = 1; cout << *it << " "; ++it; } cout << endl; }
const
迭代器单独放到一个函数中,是因为只有const
对象才需要const
迭代器,在实际中不会直接定义const
对象(没有意义),const
对象基本都是在传参的过程中产生的,由于传参为了提高效率,基本都会使用&
传参,而引用传参如果不改变对象,基本都会加const
。
容量相关
// 测试vector的默认扩容机制 void TestVectorExpand() { size_t sz; vector<int> v; sz = v.capacity(); cout << "making v grow:\n"; for (int i = 0; i < 100; ++i) { v.push_back(i); if (sz != v.capacity()) { sz = v.capacity(); cout << "capacity changed: " << sz << '\n'; } } }
从上面可以看出,随着数据的不断插入,增容的速度越来越慢,并且是按照1.5倍进行增容,但并不是说vector都是按照1.5倍进行增容,具体增容多少是和编译器的不同而有所改变。
还有就是增容的倍数并不是越大越好,倍数越大虽然可以减少增容的次数,但是有可能会导致浪费大量的空间。因此增多少是一种选择,各有利弊。若是已经确定要存储元素的个数,可以提前将空间设置足够
void TestVectorExpandOP() { vector<int> v; size_t sz = v.capacity(); v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容 cout << "making bar grow:\n"; for (int i = 0; i < 100; ++i) { v.push_back(i); if (sz != v.capacity()) { sz = v.capacity(); cout << "capacity changed: " << sz << '\n'; } } }
insert()与erase()
void test5() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); v.insert(v.begin(), 0); v.insert(v.begin(), -1); for (auto x : v) { cout << x << " "; } cout << endl; v.erase(v.begin()); for (auto x : v) { cout << x << " "; } cout << endl; }
在上面中,erase并不能删除指定的数据,而vector中并没有find函数,所以此时我们需要引入
algorithm
,#include<algorithm>
。
//要求删掉2 vector<int>::iterator pos = find(v.begin(), v.end(), 2); if (pos != v.end()) { v.erase(pos); } for (auto x : v) { cout << x << " "; } cout << endl;
find
其实是一个函数模板,如下
template<class InputIterator, class T> InputIterator find(InputIterator first, InputIterator last, const T& val) { while (first != last) { if (*first == val) return first; ++first; } return last; }
迭代器失效
迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)
引起底层空间改变的操作,迭代器可能失效
void test6() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); //迭代器失效 vector<int>::iterator it = v.begin(); v.push_back(5); v.push_back(6); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; }
从上面来看,由于在插入
5
、6
的之前it
已经被赋值,当插入5
、6
时,由于空间不够,需要开辟新的空间,销毁原来的空间,而it
任然指向的是原来的那个空间,因此此时的迭代器就已经失效了。删除操作——erase
void test7() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); v.push_back(5); v.push_back(6); vector<int>::iterator it = v.begin(); for (auto x : v) { cout << x << " "; } cout << endl; //删除偶数 while (it != v.end()) { if (*it % 2 == 0) { v.erase(it); } else { ++it; } } for (auto x : v) { cout << x << " "; } cout << endl; }
在上面代码中,由于使用
erase
删除pos
位置元素的时候,pos
之后的元素会向前移动,此时的it
没有改变,但是it所指向的元素发生了变化,变成了原来pos+1
位置的元素,此时程序就崩溃了。而之后又要进行++it
,因此就会漏掉对此时it所指向元素的判断。注意:在vscode中以上写法会导致程序崩溃,但在linux下的g++中,以上写法并不会崩溃,只是最后的结果会出错。
因为erase返回的是被删除元素后一个位置的迭代器,所以正确的写法如下
while (it != v.end()) { if (*it % 2 == 0) { it = v.erase(it); } else { ++it; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!