目录
1. vector容器遍历内置数据类型
一、C++中vector容器的介绍
std::vector 是 C++ 标准库中的一个动态数组容器,提供了动态大小的数组功能,可以在运行时动态地增加或减少元素数量。下面是关于 std::vector 的介绍和特点:
1. 动态数组
std::vector 实际上是一个封装了动态数组的类模板。它可以在运行时根据需要动态增长或缩小,不像静态数组需要在定义时确定大小。
2. 头文件
std::vector 定义在 <vector> 头文件中,使用时需要包含这个头文件: #include <vector>
3. 元素访问
可以使用下标 [] 运算符或 at() 函数访问元素。
提供了迭代器(iterator)来遍历容器中的元素。
4. 动态扩展
当向 std::vector 添加元素时,如果空间不足,它会自动分配更多的内存以容纳新的元素,通常是以当前容量的两倍进行扩展,这样可以减少频繁分配内存的开销。
5. 容器大小
可以使用 size() 函数获取当前 std::vector 中的元素数量。
可以使用 capacity() 函数获取 std::vector 内部实际分配的存储空间大小。
6. 插入和删除元素
可以使用 push_back() 在尾部添加元素。
可以使用 pop_back() 移除尾部的元素。
可以使用 insert() 在指定位置插入元素。
可以使用 erase() 移除指定位置或范围的元素。
7. 内存管理
std::vector 自动处理内存管理,包括内存分配和释放。
可以使用 reserve() 预留空间,避免多次重新分配内存。
8. 安全性
提供了边界检查,对于使用 at() 访问元素的方式,在越界时会抛出 std::out_of_range 异常。
9. 支持移动语义
std::vector 支持移动语义,可以高效地进行元素的移动和传递。
二、vector容器的基本概念
1. 定义
vector是C++标准模板库中的部分内容,中文偶尔译作“容器”,但并不准确。它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
2. 功能
vector数据结构和数组相似,也成为单端数组。
3. vector和普通数组的区别
数组是静态空间,vector可以动态扩展
4. 动态扩展
并不是在原空间之后续接新空间,而是找到更大的内存空间,然后将原数据拷贝到新空间,释放原空间。
5. 图形展示
6. 特别
vector容器的迭代器是支持随机访问的迭代器(可以跳跃式访问)。
三、vector容器的基本使用方法
1. vector容器遍历内置数据类型
示例:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void print_Vector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void myprint(int val)
{
cout << val << " ";
}
int main()
{
vector<int> v;
v.push_back(10);
v.push_back(30);
v.push_back(20);
v.push_back(50);
v.push_back(60);
// 以迭代器的方式访问
vector<int>::iterator itBegin = v.begin();// 指向第一个数
vector<int>::iterator itEnd = v.end();// 指向的是最后一个数的前一个数
cout << "第一个数:" << *itBegin << endl;
cout << "最后一个数:" << *(itEnd - 1) << endl;
cout << "第一个数:" << *v.begin() << endl;
cout << "最后一个数:" << *(v.end() - 1) << endl;
// 第一种遍历方式
cout << "第一种遍历方式" << endl;
while (itBegin != itEnd)
{
cout << *itBegin << " ";
itBegin++;
}
cout << endl;
// 第二种遍历方式
cout << "第二种遍历方式" << endl;
print_Vector(v);
// 第三种遍历方式,利用algorithm 头文件包含的内置算法,需要回调函数
cout << "第三种遍历方式,利用algorithm 头文件包含的内置算法,需要回调函数" << endl;
for_each(v.begin(), v.end(), myprint);
// 最后一个参数是回调函数,一开始不调用,只有for_each调用的时候才调用
cout << endl << "最后一个参数是回调函数,一开始不调用,只有for_each调用的时候才调用" << endl;
cout << endl;
return 0;
}
运行结果:
2. vector容器遍历自定义数据类型
示例:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class person
{
public:
person(string name, int age)
{
this->name = name;
this->age = age;
}
string name;
int age;
};
void print_Vector(vector<person>& v)
{
for (vector<person>::iterator it = v.begin(); it != v.end(); it++)
{
// 迭代器返回的类型就是<>内的类型
cout << "姓名:" << it->name << "\t年龄:" << it->age << endl;
// 也可以先*it解引用出来后(.)某个属性
cout << "姓名:" << (*it).name << "\t年龄:" << (*it).age << endl;
}
}
int main()
{
// 准备数据
person p1("张三", 10);
person p2("李四", 30);
person p3("王五", 20);
person p4("赵六", 50);
person p5("郭七", 60);
vector<person> v;
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
cout << "迭代器返回的类型就是\"<>\"内的类型" << endl;
cout << "也可以先\"*it\"解引用出来后\".\"某个属性" << endl;
print_Vector(v);
return 0;
}
运行结果:
3. vector容器的嵌套使用
示例:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void print_Vector(vector<vector<int> >& v)
{
for (vector<vector<int> >::iterator it = v.begin(); it != v.end(); it++)
{
for (vector<int>::iterator jt = it->begin(); jt != it->end(); jt++)
{
cout << *jt << " ";
}
cout << endl;
}
}
int main()
{
// 大容器
vector<vector<int> > v;
// 小容器
vector<int> v1;
vector<int> v2;
vector<int> v3;
vector<int> v4;
for (int i = 0; i < 4; i++)
{
v1.push_back(i + 1);
v2.push_back(i + 2);
v3.push_back(i + 3);
v4.push_back(i + 4);
}
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
v.push_back(v4);
print_Vector(v);
return 0;
}
运行结果:
四、vector构造函数
- vector<T> v; // 采用模板类实现,默认构造函数
- vector(v.begin(),v.end()); // 将v.begin(),v.end()区间中的元素拷贝给本身
- vector(n , elem); // 构造函数将n个elem拷贝给本身
- vector(const vector & vec); // 拷贝构造函数
示例:
#include<iostream>
#include<vector>
using namespace std;
void print_Vector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
// 默认构造,无参构造
cout << "默认构造,无参构造" << endl;
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
print_Vector(v1);
// 通过区间方式构造
vector<int> v2(v1.begin(), v1.end());
cout << "通过区间方式构造" << endl;
print_Vector(v2);
// n个elem的方式
vector<int>v3(10, 20); // 10个20
cout << "通过构建n个elem的方式构建vector" << endl;
print_Vector(v3);
// 拷贝构造
vector<int>v4(v3);
cout << "通过拷贝构造vector" << endl;
print_Vector(v4);
return 0;
}
运行结果:
五、vector赋值操作
- vector & operator=(const vector & vec); // 重载等号赋值
- assign(beg, end); // 将beg,end区间中的数据拷贝赋值给本身
- assign(n, elem); // 将n个elem拷贝赋值给本身
示例:
#include<iostream>
#include<vector>
using namespace std;
void print_Vector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
// 默认构造,无参构造
vector<int> v1;
cout << "默认构造,无参构造" << endl;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
print_Vector(v1);
// 赋值
vector<int> v2;
v2 = v1;
cout << "利用一个已经构建好的vector,直接赋值给另一个vector" << endl;
print_Vector(v2);
// assign 区间
vector<int>v3;
v3.assign(v1.begin(), v1.end());
cout << "利用assign 区间对vector进行赋值" << endl;
print_Vector(v3);
// n个elem
vector<int> v4;
v4.assign(10, 100);
cout << "利用n个elem对vector进行赋值" << endl;
print_Vector(v4);
return 0;
}
运行结果:
六、vector容量和大小
- empty(); // 判断容器是否为空
- capacity(); // 容器的容量
- size(); // 返回容器中元素的个数
- resize(); // 重新指定容器的长度为num,若容器变长则默认值填充新位置
// 如果容器变短,则末尾超出容器长度的元素被删除
- resize(); // 重新指定容器的长度为num,若容器变长,则以elem值填充新位置
// 如果容器变短,则末尾超出容器长度的元素被删除
示例:
#include<iostream>
#include<vector>
using namespace std;
void print_Vector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
// 默认构造,无参构造
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
cout << "默认构造,无参构造" << endl;
print_Vector(v1);
// 判断是否为空
v1.empty();// 判断是否为空,空返回1不空0
cout << "判断是否为空,判断是否为空,空返回1不空0" << endl;
cout << v1.empty() << endl;
// 容量
int num = v1.capacity();
cout << "v1容器的容量:" << num << endl;
// 大小
int size = v1.size();
cout << "v1容器的大小:" << size << endl;
// 重新指定大小
cout << endl << "重新指定大小" << endl;
v1.resize(15);
cout << "比原本的大小大,默认用0填充" << endl;
print_Vector(v1);// 比原本的大小大,默认用0填充
v1.resize(7);
cout << "比原本的大小小,默认删除指定大小后的元素" << endl;
print_Vector(v1);// 比原本的大小小,默认删除指定大小后的元素
// 重载版本
cout << "重新指定大小用指定数字填充" << endl;
v1.resize(15, 100);// 用100填充
print_Vector(v1);
return 0;
}
运行结果:
七、vector插入和删除
- push_back(ele); // 尾部插入元素ele
- pop_bakc(); // 删除最后一个元素
- insert(const_iterator pos, ele); // 迭代器指向位置pos插入元素ele
- insert(const_iterator pos, int count , ele); // 迭代器指向位置pos插入count个元素ele
- erase(const_iteartor pos); // 删除迭代器指向的元素
- erase(const_iterator start, const_iteartor end); // 删除迭代器从start到end之间的元素
- clear(); // 删除容器中所有元素
示例:
#include<iostream>
#include<vector>
using namespace std;
void print_Vector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
// 默认构造,无参构造
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
cout << "默认构造,无参构造" << endl;
print_Vector(v1);
// 尾删
cout << "尾删" << endl;
v1.pop_back();
print_Vector(v1);
// 插入
cout << "插入vector容器中数据,第一个参数是迭代器" << endl;
v1.insert(v1.begin(), 100); // 第一个参数是迭代器
print_Vector(v1);
cout << "插入vector容器中n个数据,第一个参数是迭代器,第二个参数是个数,第三个参数是插入的数据" << endl;
// 插入n个数
v1.insert(v1.begin(), 2, 1000);
print_Vector(v1);
// 删除
cout << "删除迭代器所在位置的数据" << endl;
v1.erase(v1.begin());// 第一个参数还是迭代器
print_Vector(v1);
// 删除区间
cout << "删除容器区间内的数据" << endl;
v1.erase(v1.begin(), v1.end());
print_Vector(v1);
// 清空
cout << "清空vector容器中的数据" << endl;
v1.clear();
print_Vector(v1);
return 0;
}
运行结果:
八、vector数据存取
- at(int idx); // 返回索引idx所指的数据
- operator[]; // 返回索引idx所指的数据
- front(); // 返回容器中第一个元素
- back(); // 返回容器中最后一个数据元素
示例:
#include<iostream>
#include<vector>
using namespace std;
void print_Vector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
// 默认构造,无参构造
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
cout << "默认构造,无参构造" << endl;
print_Vector(v1);
// 利用[]
cout << "利用[]获取数据在vector容器中的位置" << endl;
for (int i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
// 利用at
cout << "利用\".at()\"获取数据在vector容器中的位置" << endl;
for (int i = 0; i < v1.size(); i++)
{
cout << v1.at(i) << " ";
}
cout << endl;
// 返回头尾元素
cout << "第一个元素为(front()):" << v1.front() << endl;
cout << "最后一个元素为(back()):" << v1.back() << endl;
return 0;
}
运行结果:
九、互换容器
互换容器
swap(vec); // 将vec与本身的元素互换
示例:
#include<iostream>
#include<vector>
using namespace std;
void print_Vector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
cout << "交换前" << endl;
print_Vector(v1);
vector<int> v2;
for (int i = 20; i >= 0; i--)
{
v2.push_back(i);
}
print_Vector(v2);
cout << "交换后" << endl;
v1.swap(v2);
print_Vector(v1);
print_Vector(v2);
return 0;
}
运行结果:
实际应用
开辟一个很大的数组空间后,重新指定一个小一点的空间,开辟的空间不会收缩
示例:
#include<iostream>
#include<vector>
using namespace std;
void print_Vector(vector<int> &v)
{
for(vector<int>::iterator it=v.begin();it!=v.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
int main()
{
vector<int> v1;
for(int i=0;i<100000;i++)
{
v1.push_back(i);
}
cout<<"容量:"<<v1.capacity()<<endl;
cout<<"大小:"<<v1.size()<<endl;
v1.resize(3);
cout<<"重置大小;"<<endl;
cout<<"容量:"<<v1.capacity()<<endl;
cout<<"大小:"<<v1.size()<<endl;
cout<<"收缩空间:"<<endl;
vector<int>(v1).swap(v1); // 利用匿名容器实现一个交换
cout<<"容量:"<<v1.capacity()<<endl;
cout<<"大小:"<<v1.size()<<endl;
return 0;
}
运行结果;
十、vector预留空间
- reserve(int len);// 容器预留len个元素长度,预留位置不做初始化,元素不可访问
提高效率,在插入大量数据的时候,可以提前预留一个很大的空间,省去开辟空间的时间。
示例:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
// 利用reserve()预留空间
vector<int> v1;
v1.reserve(100000);
int num = 0; // 统计开辟次数
int *p = NULL;
for(int i=0;i<100000;i++)
{
v1.push_back(i);
if(p!=&v1[0])
{
p=&v1[0];
num++;
}
}
cout<<"开辟次数 "<<num<<endl;
return 0;
}
运行结果: