基本概念
vector是类型相同的对象的容器,vector的大小可以变化,可以向数组中增加元素。因此,vector容器和数组非常相似,也称为单端数组。

vector与普通数组区别:不同之处在于数组是静态空间,而vector可以动态扩展。 动态扩展并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。
- vector是将元素置于一个动态数组中加以管理的容器
- vecotr可以随机存取元素(支持索引值)直接存取,用
[]操作符或at()方法) - vector尾部添加或移除元素非常快速,但在中部或头部插入元素或移除元素比较费时
- vector的元素地址是连续的,动态扩容后可能地址会发生变化,即可能会在一块新的地址重新放新的连续的元素
vector的使用
头文件:
#include <iostream>
#include <vector>
using namespace std;
定义和初始化
像定义变量一样定义vector变量:
vector<类型名> 变量名;
初始化的方式比较多,有如下几种:
1 vector<T> v1; //v1为空,执行默认初始化
2 vector<T> v2(v1); //v2中包含v1所有元素的副本
3 vector<T> v2=v1; //等价于v2(v1)
4 vector<T> v3(n,val); //v3中包含n个重复元素,每个元素的值都是val
5 vector<T> v4(n); //v4包含n个重复执行了值初始化的对象
6 vector<T> v5{a,b,c...}; //包含初始化元素个数,每个元素被对应的赋予相应的值
7 vector<T> v5={a,b,c...}; //等价v5{a,b,c...}
类型名可以是int、double、char、struct,也可以是STL容器:vector、set、queue。
vector<int> name;
vector<double> name;
vector<char> name;
vector<struct node> name;
vector<vector<int> > name;//注意:> >之间要加空格
注意:vector<vector<int> > name;>>之间要加空格。
vector数组就是一个一维数组,如果定义成vector数组的数组,那就是二维数组**。**
vector<int> array[SZIE]; //二维变长数组
在此,我送你一句话非常受用的话:低维是高维的地址。
二维数组中,它的一维形式就是地址。例如:
#include <iostream>
using namespace std;
int main(){
int arr[3][2];//定义一个3行2列的地址
cout<<arr[0]<<endl; //输出arr第1行的地址
cout<<arr[1]<<endl; //输出arr第2行的地址
cout<<arr[2]<<endl; //输出arr第3行的地址
return 0;
}
/*运行结果:0x61fe00 //arr第1行的地址
0x61fe08 //arr第2行的地址
0x61fe10 //arr第3行的地址*/
所以,vector容器也可以这样理解。
构造函数
- 无参构造函数:
vector() - 指定大小和默认值的构造函数:
vector(size_type n,const value_type& val=value_type()) - 拷贝构造函数:
vector(const vector& x) - 使用迭代器范围的构造函数:
vector(InputIterator first,InputIterator last)
简单理解:创建
vector的方法就像是买不同规格的箱子,有的箱子是空的(无参构造),有的箱子里已经装满了指定数量的物品(指定大小和默认值),有的箱子是完全照搬另一个箱子的东西(拷贝构造),还有的是根据一个范围内的物品来装箱(迭代器范围构造)。
功能描述:创建vector容器
函数原型:
1. vector<T> v; //采用模版实现类实现,默认构造函数。T表示数据的类型,可以是int类型,也可以是string对象。
2. vector(v.begin(), v,end()); //将v[begin().end())区间(前闭后开)中的元素拷贝给本身。注意拷贝的元素是左闭右开区间
3. vector(n, elem); //构造函数将n个elem拷贝给本身。
4. vector(const vector &vec); //拷贝构造函数。
代码示例:
#include <vector>
#include <iostream>
using namespace std;
int main()
{
int iArray[]{ 1,2,3,4,5 };
vector<int> vecIntA(iArray, iArray + 5); //里面为1,2,3,4,5
//将Array[0,5)中的元素拷贝给本身
//vector<int> vecIntB(vecIntA.begin(), vecIntA.end()); //里面为1,2,3,4,5
vector<int> vecIntB(vecIntA.begin() + 2, vecIntA.begin() + 5); //里面为3,4,5
vector<int> vecIntC(3, 9); //里面为9,9,9,
vector<int> vecIntD(vecIntC); //拷贝构造函数调用,里面为9,9,9
for (int i = 0; i < vecIntD.size(); i++)
{
cout << vecIntD[i] << endl;
}
}
/*输出:9
9
9*/
总结: vector的多种构造方式没有可比性,灵活使用即可
赋值操作
功能描述: 给vector容器进行赋值
函数原型:
5. vector& operator=(const vector &vec); //重载等号操作符。
6. assign(begin,end); //将[begin,end)区间中的数据拷贝赋值给本身。
7. assign(n,elem); //将n个elem拷贝赋值给本身。
assign函数
功能:
通过assign函数改变vector内容(基于范围或者指定数量和初始值),这个容器会清除掉vector容器中以前的内容。
函数原型:
void assign(const_iterator first,const_iterator last);
void assign(size_type n,const T& x = T());
代码示例:
#include <vector>
#include <iostream>
using namespace std;
int main( )
{
// 定义三个存储int类型元素的vector容器对象,初始时它们都是空的
vector<int> v1, v2, v3;
// 定义一个vector<int>类型的迭代器,用于遍历vector容器中的元素
vector<int>::iterator iter;
// push_back 是 vector 容器提供的成员函数,用于在容器的末尾添加一个新元素。这里向 v1 容器依次添加了 10、20、30、40、50 这几个整数元素,使得 v1 容器中存储了这些值,v2同理
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
v2.push_back(1);
v2.push_back(2);
// 输出提示信息"v1 = ",准备输出v1容器中的元素
cout << "v1 = " ;
// 通过迭代器iter遍历v1容器,从起始位置(v1.begin())开始,到结束位置(v1.end())结束,
// 每次输出迭代器指向的元素(*iter),元素之间用空格隔开
for (iter = v1.begin(); iter!= v1.end(); iter++)
cout << *iter << " ";
// 输出换行符,进行换行操作
cout << endl;
cout << "v2 = ";
for (iter = v2.begin(); iter!= v2.end(); iter++)
cout << *iter << " ";
cout << endl;
// 使用赋值操作符将v1容器的所有元素复制给v2容器,会覆盖v2原来存储的元素
v2 = v1;
cout << "v2 = ";
for (iter = v2.begin(); iter!= v2.end(); iter++)
cout << *iter << " ";
cout << endl;
// 使用assign函数将v1容器中从起始位置(v1.begin())到结束位置(v1.end())的所有元素复制给v2容器
v2.assign(v1.begin(), v1.end()); // 同样会覆盖v2原来存储的元素
cout << "v2 = ";
for (iter = v2.begin(); iter!= v2.end(); iter++)
cout << *iter << " ";
cout << endl;
// 使用assign函数给v3容器重新赋值,使其包含7个元素,并且每个元素的值都为3
v3.assign(7, 3) ;
cout << "v3 = ";
for (iter = v3.begin(); iter!= v3.end(); iter++)
cout << *iter << " ";
cout << endl;
return 0;
}
/*运行结果:v1 = 10 20 30 40 50
v2 = 1 2
v2 = 10 20 30 40 50
v2 = 10 20 30 40 50
v3 = 3 3 3 3 3 3 3
*/
总结: vector赋值方式比较简单,使用operator=,或者assign都可以
容量和大小
功能描述: 对vector容器的容量和大小操作
函数原型:
8. empy(); //判断容器是否为空,空返回true,不为空返回false
9. capacity(); //容器的容量,capacity>=size
10. size(); //返回容器中元素的个数,capacity>=size
11. resize(int num); //重新指定容器的长度为num,若容器变长,则以 默认值0 填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
//如果容器变短,则末尾超出容器长度的元素被删除。
12. resize(int num, elem); //重新指定容器的长度为num,若容器变成,则以 elem值 填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
- vector 容器的容量(用 capacity 表示),指的是在不分配更多内存的情况下,容器可以保存的最多元素个数;而 vector 容器的大小(用 size 表示),指的是它实际所包含的元素个数。
- vector 容器的大小不能超出它的容量,在大小等于容量的基础上,只要增加一个元素,就必须分配更多的内存。注意,这里的“更多”并不是 1 个。换句话说,当 vector 容器的大小和容量相等时,如果再向其添加(或者插入)一个元素,vector 往往会申请多个存储空间,而不仅仅只申请 1 个。
- 一旦 vector 容器的内存被重新分配,则和 vector 容器中元素相关的所有引用、指针以及迭代器,都可能会失效,最稳妥的方法就是重新生成。
代码示例:
#include <iostream>#include <vector>#include <string>using namespace std;// 打印vector容器元素的函数void printVector(vector<int>& v){ for (vector<int>::iterator it = v.begin(); it!= v.end(); ++it){ cout << *it << " "; } cout << endl;}// vector容器构造及相关操作测试函数void test1(){ vector<int> v1; // 向容器中插入元素 for (int i = 0; i < 10; ++i){ v1.push_back(i + 1); } // 输出容器v1的元素 cout << "v1:"; printVector(v1); // 判断容器是否为空并输出相应信息以及容量、大小信息 if (v1.empty()){ cout << "容器为空!" << endl; } else{ cout << "容器不为空!" << endl; cout << "容器的容量为:" << v1.capacity() << endl; cout << "容器的大小为:" << v1.size() << endl; } cout << string(50, '-') << endl; // 重新指定大小,比原来长,默认值0填充 v1.resize(12); cout << "v1:"; printVector(v1); cout << endl; cout << string(50, '-') << endl; // 重新指定大小,比原来长,指定值1填充 v1.resize(15, 1); cout << "v1:"; printVector(v1); cout << endl; cout << string(50, '-') << endl; // 重新指定大小,比原来短,把超出的部分删除 v1.resize(10); cout << "v1:"; printVector(v1); cout << endl; cout << string(50, '-') << endl;}int main(){ test1(); return 0;}/*运行结果:v1:1 2 3 4 5 6 7 8 9 10容器不为空!容器的容量为:13容器的大小为:10--------------------------------------------------v1:1 2 3 4 5 6 7 8 9 10 0 0--------------------------------------------------v1:1 2 3 4 5 6 7 8 9 10 0 0 1 1 1--------------------------------------------------v1:1 2 3 4 5 6 7 8 9 10--------------------------------------------------*/
总结:
- 判断是否为空 — empty
- 返回元素个数 — size
- 返回容器容量 — capacity
- 重新指定大小 — resize
插入和删除
函数原型:
13. push_back(ele); //尾部插入元素ele。
14. pop_back(); //删除最后一个元素。
15. insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele。
16. insert(const_iterator pos, int count ele); //迭代器指向位置pos插入count个元素。
17. erase(const_iterator pos); //删除迭代器指向的元素。
18. erase(cons_titerator start, const_iterator end); //删除迭代器从start到end之间的元素。
19. clear(); //删除容器中所有元素。
代码示例:
#include <iostream>
#include<vector>
using namespace std;
void printVector(const vector<int>& vec)//形参使用const,避免被修改
{ //const_iterator只读迭代器
for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it)
{
cout << *it<< ",";
}
cout << endl;
}
int main()
{
vector<int> v;
for (int i = 0; i < 5; i++)
{
v.push_back(i + 1);//尾部插入元素
}
printVector(v);//1 2 3 4 5
v.insert(v.begin() + 1, 2, 100);//在第二个元素前插入2个100
printVector(v);//1 100 100 2 3 4 5
v.pop_back();//尾部删除一个元素
printVector(v);//1 100 100 2 3 4
cout << "-------------" << endl;
v.erase(v.begin());//删除第一个元素
printVector(v);//100 100 2 3 4
vector<int>::const_iterator it=v.erase(v.begin() + 1, v.end() - 1);
//删除从第二个元素到倒数第二个元素,返回下一个有效迭代器
printVector(v);//100 4
v.insert(it, 66);
printVector(v);//100 66 4
return 0;
}
数据存取
功能描述:对vector中的数据进行存取操作。
函数原型:
20. at(int idx); ///返回索引为idx所指的数据。
21. operator[]; //返回索引idx所指的数据。
22. front(); //返回容器中第一个数据元素。
23. back(); //返回容器中最后一个数据元素。
24. swap(vec); //将vec与本身的元素互换。
25. reserve(int len); //容器预留len个元素长度,预留位置不初始化,元素不可访问。
代码示例:
#include <iostream>
#include<vector>
using namespace std;
void printVector(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);
}
//利用[]方式访问数组中元素
for (int i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
//利用at方式访问元素
for (int i = 0; i < v1.size(); i++)
{
cout << v1.at(i) << " ";
}
cout << endl;
//获取第一个元素
cout << "第一个元素为:" << v1.front() << endl;
//获取最后一个元素
cout << "最后一个元素为:" << v1.back() << endl;
return 0;
}
/*运行结果:0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
第一个元素为:0
最后一个元素为:9
互换容器
功能描述:实现两个容器内元素进行互换。
函数原型:
24. swap(vec); //将vec与本身的元素互换。
代码示例:
#include <iostream>
#include<vector>
using namespace std;
//vector容器互换
void printVector(vector<int>v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//1、基本使用
void test06()
{
cout << "交换前:" << endl;
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
vector<int>v2;
for (int i = 10; i > 0; i--)
{
v2.push_back(i);
}
printVector(v2);
cout << "交换后:" << endl;
v1.swap(v2);
printVector(v1);
printVector(v2);
}
//2、实际用途
//巧用swap可以收缩内存空间
void test07()
{
vector<int>v;
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
}
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
v.resize(3); //重新指定大小
cout << "v的容量为:" << v.capacity() << endl; //resize操作,容量并没有变,多余的容量浪费了
cout << "v的大小为:" << v.size() << endl;
//巧用swap收缩内存
vector<int>(v).swap(v); //vector<int>(v)创建了一个为匿名对象,会按v的大小初始化这个匿名对象容器的大小
//.swap(v)会对匿名对象容器与原容器做一个交换,则原容器的指针指向匿名对象的容器,匿名对象的容器的指针改为指向原容器
// 系统运行完创建匿名函数这一句语句后对匿名对象的指针(即地址、内存)进行回收
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
}
int main()
{
test06();
test07();
return 0;
}
vector的迭代器
vector容器的迭代器是支持随机访问的迭代器

可以看到vector是左闭右开的容器,常用的迭代器是v. begin() 和v.end(),前者指向第一个元素,后者指向最后一个元素的下一个位置。vector容器还封装了很多对外接口,比如插值insert()、尾插法push_back()、尾删法pop_back()等等。
vector储存自定义数据类型
比如结构体
struct Student {
string name; // 名字
int age; // 年龄
};
int main() {
vector<Student> class1; // 班级
Student stu1, stu2;// 学生1,学生2
stu1.name = "luobo";
stu1.age = 12;
stu2.name = "xiaoming";
stu2.age = 25;
class1.push_back(stu1);
class1.push_back(stu2);
return 0;
}
可以用下面的方式使用vector定义二维数组:
vector<vector<int>> vecvec = {{1, 2, 8}, {2, 4, 9}, {4, 7, 10}, {6, 8, 11}};
我们可以通过一个构造函数快速构建这样的一个动态数组,而用构造函数的写法和用循环是等价的。

2109

被折叠的 条评论
为什么被折叠?



