本文最后更新于:2021年4月14日 晚上
序列容器vector。
iterator——迭代器
迭代器与指针类似,可以访问顺序容器与关联容器中的元素。
声明方法
容器名::iterator 变量名 //由此声名该容器的迭代器。
1 2 3 4 5 6 7
| vector<int>::iterator iter;
vector<int>::const_iterator cit;
*cit++;
|
const_iterator
对象其自身的值可以改(可以指向其他元素),但不能改写其指向的元素值.
begin与end迭代器
每种容器都定义了begin
与end
的函数,用于返回迭代器。
应用:遍历容器操作
1 2 3 4
| for(iter=vec.begin();iter!=vec.end();iter++) { cout<<*iter<<endl; }
|
其他操作
指针上的操作iterator基本上都是全部满足的。而两个迭代器相减返回的是两迭代器在容器内的差值。
vector——动态数组
头文件 #include<vector>
- vector是一种可变大小数组的序列容器,采用连续的存储空间来存储元素,可以使用数组下标的方式访问vector的元素。
- 动态存储:刚开始vector会自动分配一段连续的内存空间,当存储元素超过预配空间之后,vector会重新分配空间,拷贝数据,释放旧内存。
- vector可以高效访问元素、在末尾添加元素和删除元素,但vector对元素操作的复杂度是根据到末尾的距离成正比。
- vector是一个单口的容器,适用于在末尾进行频繁的查出删除,但不适合频繁移动元素,这会引起整体元素的移动,降低效率。
vector的声明与初始化
1 2 3 4 5
| vector<int> vec; vector<int> v2(vec); vector<int> v3 = vec; vector<int> vec(5); vector<int> vec(10,1);
|
Vector中括号初始化与返回值
1 2 3 4 5 6 7 8
| vector<int> vec{a,b,c...}; vector<int> vec ={a,b,c};
vector<int> twoSum(vector<int>& nums, int target) { return {i,j}; }
|
- vector作函数返回值时,直接返回
{}
这种形式也是可以的。
vector访问元素
- vector可使用数组下标的形式访问对应索引位置的元素,但是不能使用下标形式添加元素。
at(int idx);
//返回索引idx所指的数据,如果idx越界,抛出out_of_range异常。
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 31 32 33 34 35 36
| empty();
capacity();
size();
resize(int num);
resize(int num, elem);
push_back(ele);
pop_back();
insert(const_iterator pos, ele);
insert(const_iterator pos, int count,ele);
erase(const_iterator pos);
erase(const_iterator start, const_iterator end);
clear();
at(int idx);
operator[];
front();
back();
swap(vec);
reserve(int len);
|
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 31 32 33 34 35 36 37 38 39
| void test1() {
vector<int> vec;
int num = 0; int* p = nullptr;
for (int i = 0; i < 100000; i++) { vec.push_back(i);
if (p != &vec[0]) { p = &vec[0]; num++; } }
cout << "不预留空间 :num = " << num << endl; }
void test2() {
vector<int> vec;
vec.reserve(100000);
int num = 0; int* p = nullptr;
for (int i = 0; i < 100000; i++) { vec.push_back(i);
if (p != &vec[0]) { p = &vec[0]; num++; } }
cout << "预留空间 :num = " << num << endl; }
|
- 每当p值不等于vec的首地址时,说明vector已经自动进行了内存的扩展。
运行结果:
1 2
| 不预留空间 :num = 30 预留空间 :num = 1
|
如果预先知道了要使用多少存储空间,那么提前预留空间可以避免vector自动进行内存扩展,可以提高效率。
vector使用swap收缩内存
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
| void test3() {
vector<int> vec;
for (int i = 0; i < 100000; i++) vec.push_back(i);
cout << "初始时:" << endl; cout << "vec capacity= " << vec.capacity() << endl; cout << "vec size= " << vec.size() << endl;
vec.resize(3);
cout << "重置大小之后:" << endl; cout << "vec capacity= " << vec.capacity() << endl; cout << "vec size= " << vec.size() << endl;
vector<int>(vec).swap(vec);
cout << "收缩内存之后:" << endl; cout << "vec capacity= " << vec.capacity() << endl; cout << "vec size= " << vec.size() << endl;
}
|
运行结果:
1 2 3 4 5 6 7 8 9
| 初始时: vec capacity= 138255 vec size= 100000 重置大小之后: vec capacity= 138255 vec size= 3 收缩内存之后: vec capacity= 3 vec size= 3
|
vector<int>(vec)
表示使用vector的拷贝构造函数来创建一个匿名对象,实际上就是使用vec当前有的元素来初始化这个匿名对象的内存。
- 调用
swap(vec)
之后,匿名对象与vec这个容器会进行元素交换。
- 当前行执行结束之后,匿名对象会被系统释放掉,从而原来分配的那么一大段内存空间就被释放掉了。
使用情景
迭代器失效
- insert插入元素之后
- 若引起扩容,原来所有的迭代器都失效
- 若没有扩容,后半段迭代器失效!