C++中vector容器的基本使用
在B站听黑马程序员c++课程的记录
一些知识点
- vector数据结构和数组非常相似,也称为单端数组
- 不同之处在于数组是静态空间,一旦分配了内存就定了存储空间。而vector可以动态扩展
- 动态扩展:并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。重新换了一个地方存储。
- vector容器的迭代器是支持随机访问的迭代器,可以跳跃式访问,比如v.Begin()+4
基本使用P186-P188
-
创建vector容器对象,通过模板参数<>指定容器中存放的数据的类型
eg:vector<int> v;
-
向v的尾部增加数据
v.push_back(10);
-
使用迭代器遍历容器中的元素
由于每一个容器都有自己的迭代器,vector<int>::iterator
是在拿到vector< int >这种容器的迭代器类型即 int*,所以pBegin
指向v的第一个元素,pEnd
指向v的最后一个元素的下一个位置。*pBegin
是v的第一个元素的值,类型为int
。vector<int>::iterator pBegin = v.begin(); vector<int>::iterator pEnd = v.end();
for循环遍历
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << endl; }
-
使用STL提供标准遍历算法
for_each
,需包含头文件<algorithm>
for_each(开始指针 结束指针 仿函数)
,调用的函数不需要写参数,在for_each内部会传入v的各个值void MyPrint(int val) { cout << val << endl; } for_each(v.begin(), v.end(), MyPrint); //
嵌套vector的遍历
容器嵌套容器,在遍历中,外轮迭代的*it
是 类型为 vector<int>
的v1,v2,v3,v4。内部迭代的*vit
是v1,v2,v3,v4中存储的int
类型的数据
vector< vector<int> > v;
vector<int> v1;
vector<int> v2;
vector<int> v3;
vector<int> v4;
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
v.push_back(v4);
for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++) {
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++) {
cout << *vit << " ";
}
cout << endl;
}
p197后 vector构造函数
创建vector
vector<T> v;
//采用模板实现类实现,默认构造函数vector<int> v1;
vector(v.begin(), v.end());
//将v[begin(), end())前闭后开区间中的元素拷贝给本身。vector<int> v2(v1.begin(), v1.end());
vector(n, elem);
//构造函数将n个elem拷贝给本身。vector<int> v3(10, 100);
vector(const vector &vec);
//拷贝构造函数。vector<int> v4(v3);
赋值
通过重载=或assign成员函数
vector& operator=(const vector &vec);
//重载等号操作符v2 = v1;
assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。v3.assign(v1.begin(), v1.end());
assign(n, elem);
//将n个elem拷贝赋值给本身。v4.assign(10, 100);
容量和大小
empty();
//判断容器是否为空v1.empty()
capacity();
//容器的容量v1.capacity()
size();
//返回容器中实际元素的个数 size一定<capacityresize(int num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。resize(int num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
/resize函数中如果容器变短,则末尾超出容器长度的元素被删除
vector插入和删除
push_back(ele);
//尾部插入元素elev1.push_back(1);
pop_back();
//删除最后一个元素v1.pop_back();
insert(const_iterator pos, ele);
//迭代器指向位置pos插入元素elev1.insert(v1.begin(), 100);
insert(const_iterator pos, int count,ele);
//迭代器指向位置pos插入count个元素elev1.insert(v1.begin(), 2, 1000);
erase(const_iterator pos);
//删除迭代器指向的元素v1.erase(v1.begin());
erase(const_iterator start, const_iterator end);
//删除迭代器从start到end之间的元素v1.erase(v1.begin(), v1.end());
clear();
//删除容器中所有元素v1.clear();
数据存取 访问
除了迭代器可以访问所有元素外,还有一下几种访问元素的方式
at(int idx);
//返回索引idx所指的数据v1.at(i)
operator[];
//返回索引idx所指的数据v1[i]
front();
//返回容器中第一个数据元素v1.front()
back();
//返回容器中最后一个数据元素v1.back()
vector互换容器
swap(vec);
成员函数实现两个容器内元素进行互换 v1.swap(v2);
- 巧用swap可以收缩内存空间,一开始v的size是100000,capacity是130000+(vector类中自动有算法算出的capacity)。
v.resize(3)
重新指定v的size之后,v的size变为3,而capacity依旧是130000+。
此时,vector<int>(v)
相当于调用了拷贝构造函数生成了一个匿名对象,按照v实际用的元素个数3初始化匿名对象,size是3,capacity也是3。交换之后v的size变为3,capacity也是3。
vector<int> v;
for (int i = 0; i < 100000; i++) {
v.push_back(i);
}
//一开始v的size是100000,capacity是130000+(vector类中自动有算法算出的capacity)
v.resize(3);//重新指定v的大小后,
vector<int>(v).swap(v); //收缩内存
vector预留空间
reserve(int len);
使容器预留len个元素长度,预留位置不初始化,元素不可访问(与resize不同)。
由于vector类中自动有算法根据size的内容算出capacity。一旦size要超过capacity,就重新分配新的空间,释放原有空间。10000个数需要转移30次。如果一开始就预留10000个空间,就不需要转移。可以减少vector在动态扩展容量时的扩展次数。