文章目录
1 vector基本概念
作用:单端数组
,仅可在容器的尾部插入或删除元素,与数组非常相似。
区别:普通数组
是静态空间;vector
支持动态扩展容量机制。
动态扩展:并非在原有内存空间中扩展新空间,而是申请更大的内存空间,将原有数据拷贝至新的内存空间,并释放原有内存空间。
vector容器的迭代器:支持随机访问的迭代器,可跳跃式访问容器元素。
push_back()
:尾插法插入数据。
pop_back()
:尾删法删除数据。
front()
:获取vector容器的第1个元素。
back()
:获取vector容器的最后1个元素。
begin()
:获取起始迭代器,指向容器中的第1个元素。
end()
:获取结束迭代器,指向容器中的最后1个元素的下一个位置。
2 vector构造函数
作用:创建vector容器。
注:使用vector容器时,需包含头文件
#include <vector>
。
函数原型:
(1)vector<T> v;
:默认无参构造函数,采用类模板实现。
(2)vector(v.begin(), v.end());
:拷贝容器对象v
的[begin(), end())
区间(左闭右开,包左不包右)的元素进行初始化。
(3)vector(n, elem);
:有参构造函数,使用n
个elem元素
进行初始化。
(4)vector(const vector &vec);
:拷贝构造函数,使用已有vector对象初始化新的对象。
注:通常使用默认无参构造函数和拷贝构造函数实例化vector容器对象。
示例:vector构造函数
#include <iostream>
using namespace std;
#include <vector> //包含头文件
//打印vector元素的函数模板
template<typename T>
void printVector(vector<T>& v) {
//for循环遍历
for (vector<T>::iterator it = v.begin(); it != v.end(); it++) {
cout << (*it) << " ";
}
cout << endl;
}
int main() {
/* 1.默认无参构造函数 */
vector<int> v1;
//尾插法插入元素
for (int i = 0; i < 5; i++) {
v1.push_back(i);
}
//遍历
printVector<int>(v1); //0 1 2 3 4
/* 2.有参构造,区间拷贝 */
//左闭右开区间的元素
vector<int> v2(v1.begin(), v1.end());
printVector<int>(v2); //0 1 2 3 4
/* 3.n个elem元素赋值 */
//5个整型元素6
vector<int> v3(5, 6);
printVector<int>(v3); //6 6 6 6 6
/* 4.拷贝构造函数 */
vector<int> v4(v3);
printVector<int>(v4); //6 6 6 6 6
return 0;
}
3 vector赋值操作【operator=、assign()】
作用:通过重载赋值运算符operator=
和成员函数assign()
,对vector容器进行赋值。
函数原型:
(1)vector& operator=(const vector &vec);
:重载赋值运算符,使用目标vector容器,对当前vector容器赋值。
(2)assign(begin, end);
:拷贝目标vector容器中[begin(), end())
区间(左闭右开,包左不包右)的元素,对当前vector容器赋值。
(3)assign(n, elem);
:使用n
个elem元素
,对当前vector容器赋值。
示例:vector赋值操作
#include <iostream>
using namespace std;
#include <vector> //包含头文件
//打印vector元素的函数模板
template<typename T>
void printVector(vector<T>& v) {
//for循环遍历
for (vector<T>::iterator it = v.begin(); it != v.end(); it++) {
cout << (*it) << " ";
}
cout << endl;
}
int main() {
vector<int> v;
//尾插法插入元素
for (int i = 0; i < 5; i++) {
v.push_back(i);
}
//遍历
printVector<int>(v); //0 1 2 3 4
/* 1.重载运算符=赋值 */
vector<int> v1 = v;
printVector<int>(v1); //0 1 2 3 4
/* 2.assign()函数,区间拷贝 */
//左闭右开区间的元素
vector<int> v2;
v2.assign(v.begin(), v.end());
printVector<int>(v2); //0 1 2 3 4
/* 3.assign()函数,n个elem元素赋值 */
vector<int> v3;
//6个整型元素6
v3.assign(6, 6);
printVector<int>(v3); //6 6 6 6 6 6
return 0;
}
4 vector容量【capacity()】和大小【size()、resize()】
作用:操作vector容器的容量和大小(即元素个数)。
注:容器的容量始终大于等于容器的大小(即元素个数),并支持动态扩展容量。
函数原型:
(1)empty();
:判断容器是否为空。
(2)capacity();
:获取容器的容量。
(3)size();
:获取容器的大小,即元素个数。
(4)resize(int num);
:重新指定容器的长度为num
。
若容器变长,则以默认值0
填充新位置;若容器变短,则容器末尾超出新长度的元素被删除。
(5)resize(int num, elem);
:重新指定容器的长度为num
。
若容器变长,则以指定值elem
填充新位置;若容器变短,则容器末尾超出新长度的元素被删除。
示例:vector容量和大小
#include <iostream>
using namespace std;
#include <vector> //包含头文件
//打印vector元素的函数模板
template<typename T>
void printVector(vector<T>& v) {
//for循环遍历
for (vector<T>::iterator it = v.begin(); it != v.end(); it++) {
cout << (*it) << " ";
}
cout << endl;
}
int main() {
vector<int> v1;
//尾插法插入元素
for (int i = 0; i < 5; i++) {
v1.push_back(i);
}
printVector<int>(v1); //0 1 2 3 4
//empty():判断容器是否为空
cout << (v1.empty() ? "v1为空" : "v1不为空") << endl; //v1不为空
//capacity(); :获取容器的容量。
cout << "v1的容量:" << v1.capacity() << endl; //6(随机值)
//size(); :获取容器的大小,即元素个数。
cout << "v1的大小/元素个数:" << v1.size() << endl; //5
//resize(int num);:重新指定容器的长度为num
//若容器变长,则以默认值0填充新位置;若容器变短,则容器末尾超出新长度的元素被删除。
v1.resize(10); //长度变大时,使用默认值0填充
printVector<int>(v1); //0 1 2 3 4 0 0 0 0 0
v1.resize(3); //长度变小时,容器末尾超出新长度的元素被删除
printVector<int>(v1); //0 1 2
//resize(int num, elem); :重新指定容器的长度为num。
//若容器变长,则以指定值elem填充新位置;若容器变短,则容器末尾超出新长度的元素被删除。
v1.resize(8, 6); //长度变大时,使用指定值6填充
printVector<int>(v1); //0 1 2 6 6 6 6 6
return 0;
}
5 vector插入【push_back()、insert()】和删除【pop_back()、erase()、clear()】
(1)vector容器插入元素:使用成员函数push_back(..)
、insert(..)
向vector容器插入元素。
函数原型:
①push_back(ele);
:尾插法,向vector容器的尾部插入元素ele
。
②insert(const_iterator pos, ele);
:迭代器指向位置pos
插入元素ele
③insert(const_iterator pos, int n, ele);
:迭代器指向位置pos
插入n
个元素ele
。
(2)vector容器删除元素:使用成员函数pop_back(..)
、erase(..)
、clear(..)
删除vector容器中的元素。
函数原型:
①pop_back();
:尾删法,删除vector容器尾部的最后1个元素。
②erase(const_iterator pos);
:删除迭代器指向位置的元素。
③erase(const_iterator start, const_iterator end);
:删除迭代器指向位置[start, end)
区间的所有元素。
④clear();
:清空容器中的所有元素。
注1:清空容器的所有元素,
v.clear();
等价于v.erase(v.begin(), v.end());
。
注2:插入元素insert(..)
、删除元素erase(..)
均需要迭代器对象作为参数。
示例:vector插入和删除元素
#include <iostream>
using namespace std;
#include <vector> //包含头文件
//打印vector元素的函数模板
template<typename T>
void printVector(vector<T>& v) {
//for循环遍历
for (vector<T>::iterator it = v.begin(); it != v.end(); it++) {
cout << (*it) << " ";
}
cout << endl;
}
int main() {
vector<int> v;
//插入元素:push_back()
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
printVector<int>(v); //1 2 3 4 5
//删除元素:pop_back()
v.pop_back();
printVector<int>(v); //1 2 3 4
//插入元素:insert(const_iterator pos, ele); 迭代器指向位置pos插入元素ele
//在起始迭代器的指向位置插入元素10
v.insert(v.begin(), 10);
printVector<int>(v); //10 1 2 3 4
//插入元素:insert(const_iterator pos, int n, ele); 迭代器指向位置pos插入n个元素ele。
//在起始迭代器的指向位置插入2个元素0
v.insert(v.begin(), 2 , 0);
printVector<int>(v); //0 0 10 1 2 3 4
//删除元素:erase(const_iterator pos); 删除迭代器指向位置的元素
//删除起始迭代器的指向位置的元素
v.erase(v.begin());
printVector<int>(v); //0 10 1 2 3 4
//删除元素:erase(const_iterator start, const_iterator end); 删除迭代器指向位置[start, end)区间的所有元素。
//删除起始迭代器后一个位置 至 结束迭代器 之间区间的所有元素
v.erase(++v.begin(), v.end());
printVector<int>(v); //0
//清空元素:clear(); 清空容器中的所有元素。
v.clear();
printVector<int>(v); //(空)
return 0;
}
6 vector数据存取【operator[]、at()】
作用:通过重载赋值运算符operator[]
和成员函数at(int index)
,对vector容器的单个元素进行读(作为右值)或写(作为左值)。
函数原型:
(1)operator[](int index);
:重载运算符[],读写指定索引位置index
的元素。
(2)at(int index);
:成员函数,读写指定索引位置index
的元素。
(3)front();
:返回容器的第1个元素。
(4)back();
:返回容器的最后1个元素。
访问/遍历vector容器元素的方式:
①迭代器
②重载运算符[]
③成员函数at()
示例:vector读写元素
#include <iostream>
using namespace std;
#include <vector> //包含头文件
//打印vector元素的函数模板
template<typename T>
void printVector(vector<T>& v) {
//for循环遍历
for (vector<T>::iterator it = v.begin(); it != v.end(); it++) {
cout << (*it) << " ";
}
cout << endl;
}
int main() {
vector<int> v;
//尾插法插入元素
for (int i = 0; i < 5; i++) {
v.push_back(i);
}
//遍历方式1:重载运算符
for (int i = 0; i < v.size(); i++) {
//重载运算符[]:读写指定索引位置index的元素。
cout << v[i] << " "; //0 1 2 3 4
}
cout << endl;
//遍历方式2:成员函数at()
for (int i = 0; i < v.size(); i++) {
//重载运算符[]:读写指定索引位置index的元素。
cout << v.at(i) << " "; //0 1 2 3 4
}
cout << endl;
//修改元素1:重载运算符
v[4] *= 10;
printVector<int>(v); //0 1 2 3 40
//修改元素2:成员函数at()
v.at(0) = -1;
printVector<int>(v); //-1 1 2 3 40
//获取第1个元素
cout << "第1个元素:" << v.front() << endl; //-1
//获取最后1个元素
cout << "最后1个元素:" << v.back() << endl; //40
return 0;
}
7 vector互换容器【swap()】
函数原型:swap(vec);
:将目标vector容器vec
的元素与自身互换。
作用:
(1)实现两个vector容器的元素互换。
(2)可结合匿名对象
和拷贝构造函数,实现容器内存收缩,如:vector<int>(v).swap(v);
。
背景:当容量较大的vector容器,使用成员函数resize()
将容器的大小(元素个数)调整至较小值时,vector容器实际容量不变,导致内存资源浪费。
内存收缩步骤:
①vector<int>(v)
:调用拷贝构造函数创建vector类的匿名对象,将根据原vector容器对象v
的大小(元素个数)分配一定的容量(较小值)。
②vector<int>(v).swap(v);
:原vector对象v
和匿名对象实现容器互换,即指针指向的内存地址互换,匿名对象指向具有较大容量的内存空间。
③匿名对象调用完毕后立即释放,对应的较大容量的内存空间被自动释放。
④原vector对象v
现指向具有较小容量的内存空间,实现容器内存收缩。
示例:vector容器互换
#include <iostream>
using namespace std;
#include <vector> //包含头文件
//打印vector元素的函数模板
template<typename T>
void printVector(vector<T>& v) {
//for循环遍历
for (vector<T>::iterator it = v.begin(); it != v.end(); it++) {
cout << (*it) << " ";
}
cout << endl;
}
//vector容器互换
void func1() {
vector<int> v1;
for (int i = 0; i < 5; i++) {
v1.push_back(i);
}
vector<int> v2;
for (int i = 4; i >= 0; i--) {
v2.push_back(i);
}
cout << "交换前v1容器:" << endl;
printVector<int>(v1); //0 1 2 3 4
cout << "交换前v2容器:" << endl;
printVector<int>(v2); //4 3 2 1 0
//容器互换
v1.swap(v2);
cout << "交换后v1容器:" << endl;
printVector<int>(v1); //4 3 2 1 0
cout << "交换后v2容器:" << endl;
printVector<int>(v2); //0 1 2 3 4
}
//实际作用:vector容器内存收缩
void func2(){
//现有容器v开始时具有较大容量和较多元素
vector<int> v;
for (int i = 0; i < 100000; i++) {
v.push_back(i);
}
cout << "resize前..." << endl;
cout << "v的容量:" << v.capacity() << endl; //容量:138255
cout << "v的大小:" << v.size() << endl; //大小:100000
/* resize() 重新指定大小,长度为5 */
v.resize(5);
//resize容器大小后,容量保持【较大值】不变,容器大小变为【较小值】
//内存资源浪费
cout << "resize后..." << endl;
cout << "v的容量:" << v.capacity() << endl; //容量:138255
cout << "v的大小:" << v.size() << endl; //大小:5
/* 创建匿名对象,并进行容器互换 */
vector<int>(v).swap(v);
//容器互换后,原vector容器的容量和大小均变为【较小值】,实现容器内存收缩
//匿名对象调用完毕后立即释放,指向的较大内存空间被释放
cout << "容器互换后..." << endl;
cout << "v的容量:" << v.capacity() << endl; //容量:5
cout << "v的大小:" << v.size() << endl; //大小:5
}
int main() {
//func1();
func2();
return 0;
}
8 vector预留空间【reserve()】
作用:当vector容器存储的数据量较大时,一开始可利用成员函数reserve()
预留指定大小的内存空间,减少vector容器在动态扩展容量时的扩展次数,降低数据拷贝过程的资源消耗。
函数原型:
reserve(int len);
:容器预留len
个元素长度的内存空间,但预留内存空间不进行初始化,不可访问。
注:
reserve(...)
和reverse()
需注意区分。
reserve(...)
用于vector容器预留空间;
reverse(...)
用于反转容器的元素,如reverse(v.begin(), v.end());
。
示例:vector预留空间
#include <iostream>
using namespace std;
#include <vector> //包含头文件
//vector预留空间
void func() {
vector<int> v;
/* 预留空间 */
//v.reserve(10000); //动态扩展7次
//v.reserve(20000); //动态扩展5次
//v.reserve(50000); //动态扩展3次
v.reserve(100000); //动态扩展1次
//统计vector插入100000个元素时,动态扩展容量的总次数
int count = 0;
//初始化空指针,用于判断是否动态扩展
int* p = NULL;
for (int i = 0; i < 100000; i++) {
v.push_back(i);
//判断指向vector容器首元素的指针,记录的地址值是否发生改变
//首地址发生改变 → vector容器已动态扩展
if (p != &v[0]) {
//更新指针的地址值
p = &v[0];
count++;
//cout << "vector容器的首地址:" << p << endl;
}
}
cout << "动态扩展容量的总次数:" << count << endl;
//未预留空间时:动态扩展30次
//预留10000个元素长度时:动态扩展7次
//预留20000个元素长度时:动态扩展5次
//预留50000个元素长度时:动态扩展3次
//预留100000个元素长度时:动态扩展1次
}
int main() {
func();
return 0;
}