目录
一.vector介绍
vector是STL(标准模板库)中的一个序列式容器,本质是一个类模板。
每一个STL库都需要包含对应的头文件,所以使用vector第一步是:
#include <vector>
vector和数组的区别是:vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间容纳新元素。
vector也可以解释为单端数组
二.vector初始化
1.初始化vector的方法
vector<T> v1 | v1是一个空vector,元素类型为T,执行默认初始化 |
vector<T> v2(v1) | 把v1的元素拷贝给v2 |
vector<T> v2=v1 | 把v1的元素拷贝给v2 |
vector<T> v3(n,val) | v3包含了n个重复的元素,每个元素的值都是val |
vector<T> v4(n) | v4包含了n个重复的元素,每个元素的值都是0 |
vector<T> v5{a,b,c,...} | v5包含了列表中个数的元素,每个元素对应相应的值 |
vector<T> v6={a,b,c,...} | 和上面v5等价 |
2.vector拷贝vector对象
允许把一个vector对象元素拷贝给另一个vector对象,注意两个vector对象的类型必须相同。
vector<T> v2(v1) //把v1的元素拷贝给v2
vector<T> v2(v1.begin(),v1.end()) //把v1的[brgin,end)前闭后开数据拷贝给v2
vector<T> v2=v1 //把v1的元素拷贝给v2,重载运算符=
3.列表初始化(花括号)
vector<T> v5{a,b,c,...} //v5包含了列表中个数的元素,每个元素对应相应的值
vector<T> v6={a,b,c,...} //和上面v5等价
4.值初始化(圆括号)
vector<T> v3(n,val) //v3包含了n个重复的元素,每个元素的值都是val
vector<T> v4(n) //v4包含了n个重复的元素,每个元素的值都是0
5. 列表初始化和值初始化注意点
(1) 如果提供的书初始值列表,则只能把初始值放在花括号中进行列表初始化,不能放进圆括号中
vector<string> v7("a","b","c") //错误!不能用圆括号初始化值列表
(2) 花括号中的值与元素类型不同,会尝试用值初始化列表
vector<string> v8{10,"hi"} //转换使用值初始化
三.向vector对象中添加元素
1.什么时候使用值初始化?
(1)初始值已知且数量较少
(2)初始值是另外一个vector对象的副本
(3)所有元素初始值都一样
但是当元素各不相同且数量很多时,值初始化就不方便了。
2.push_back()方法
vector<int> v1; //创建一个空vector
for(i=0;i!=100;i++)
{
v1.push_back(i); //依次添加到v1的尾端
//循环后v1有100个元素,0-99
}
3.不能使用下标添加元素
vector<int> v2; //创建一个空vector
v2[0] = 1; //错误!
只能用下标读取元素
四.vector其他操作
引用黑马程序员C++教程中的图:
为什么capacity()>=size() 参考九.vector的数据结构
v.empty(); | v中不含任何元素,返回真;否则返回假 |
v.size(); | 返回v中元素个数 |
v1.assign(v2.begin(), v2.begin()+3); | 赋值:将v2的0~2个元素构成的向量赋给v1 |
v.assign(4,2) | 赋值:v只含4个元素,且每个元素为2 |
v.back(); | 返回v的最后一个元素 |
v.front(); | 返回v的第一个元素 |
v[i]; | 返回v的第i个元素,当且仅当v[i]存在 |
v.clear(); | 清空v中的元素 |
v.pop_back(); | 删除v向量的最后一个元素 |
v.erase(v.begin()+1,v.begin()+3); | 删除v中第1个(从第0个算起)到第2个元素 |
v.insert(v.begin()+1,5); | 在v的第1个元素(从第0个算起)的位置插入数值5,如v为1,2,3,4,插入元素后为1,5,2,3,4 |
v.insert(v.begin()+1,3,5); | 在v的第1个元素(从第0个算起)的位置插入3个数,其值都为5 |
v.insert(v.begin()+1,b+3,b+6); | //b为数组,在v的第1个元素(从第0个算起)的位置插入b的第3个元素到第5个元素 |
v.capacity(); | 返回v在内存中总共可以容纳的元素个数 |
v.resize(10); | 将v的现有元素个数调至10个,多则删,少则补,其值随机 |
v.resize(10,2); | 将v的现有元素个数调至10个,多则删,少则补,其值为2 |
v.reserve(100); | 将v的容量(capacity)扩充至100 |
v1.swap(v2); | v2为向量,将v1中的元素和v2中的元素进行整体性交换 |
v1==v2; | v2为向量,向量的比较操作还有!=,>=,<=,>,< |
五. vector与vector::iterator
1.二者关系
每种容器类型都定义了自己的迭代器类型,如vector:
vector<int>::iterator iter;
vector<int>是声明向量容器;
例如 verctor<int> v,就是创建了一个名字叫v的向量容器。
vector<int>::iterator是定义向量迭代器
例如,vector<int>::iterator iter 就是定义了一个名字叫iter 的向量迭代器
iter 实质上是一个迭代器指针,访问时需要解引用*iter,解引用后的数据类型和<int>相同。
2.begin和end操作
每种容器都定义了一对命名为begin和end的函数,用于返回迭代器。如果容器中有元素的话,由begin返回指向第一个元素的迭代器
vector<int>::iterator iter = v.begin();
//这条语句把迭代器iter初始化为由名为begin的vector操作的返回值。如果vector非空,初始化后,iter即指该元素为v[0]
由end操作返回的一个指向vector的末端元素的下一个迭代器。称为“超出末端迭代器”,表明它指向了一个不存在的元素。如果噢vector为空,begin返回的迭代器与end返回的迭代器相同。
//用迭代器遍历输出容器中的元素
容器名::iterator iter;
for(iter = 容器.begin();iter != 容器.end();iter++)
{
cout << *iter << ' ';
}
六.遍历vector的方法
1.用迭代器遍历输出容器中的元素
std::vector<int>::iterator iter;
for(iter = v.begin();iter != v.end();iter++)
{
cout << *iter << ' ';
}
2.使用STL算法for_each()
引入头文件
#include <algorithm>
void myPrint(int val)
{
cout<<val<<endl;
}
for_each(v.begin,v.end,myPrint) //myPrint回调函数
七.vector存放自定义数据类型
it实质上是一个迭代器指针,访问时需要解引用*it,解引用后的数据类型和<Person>相同。
1.vector存放class类型
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Person
{
public:
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
int main()
{
vector<Person> v;
Person p1("Mike", 20);
Person p2("Simth", 21);
Person p3("Lily", 22);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
//cout << "姓名:" << (*it).m_name<< endl;
cout << "姓名:" << it->m_name<< endl;
cout << "年龄:" << it->m_age<< endl;
}
system("pause");
return 0;
}
2.vector存放指针类型
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Person
{
public:
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
int main()
{ //存放指针类型
vector<Person*> v;
Person p1("Mike", 20);
Person p2("Simth", 21);
Person p3("Lily", 22);
//&取地址符
v.push_back(&p1);
v.push_back(&p2);
v.push_back(&p3);
for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++)
{
//cout << "姓名:" << *(*it).m_name<< endl;
cout << "姓名:" << (*it)->m_name<< endl;
cout << "年龄:" << (*it)->m_age<< endl;
}
system("pause");
return 0;
}
八.vector嵌套vector容器
这种嵌套关系有点类似于二维数组。主要还是要注意(*it)<==>vector<int>,(*vit)<==>int
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<vector<int>> v;
//创建小容器
vector<int> v1;
vector<int> v2;
vector<int> v3;
//向小容器中添加数据
for (int i = 0; i < 5; i++)
{
v1.push_back(i + 1);
v2.push_back(i + 2);
v3.push_back(i + 3);
}
//将小容器插入到大容器中
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
//通过大容器把所有数据遍历一遍
for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++)
{
//(*it)的类型是vector<int>
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
{
//(*vit)的类型是int
cout << (*vit) << " ";
}
cout << endl;
}
system("pause");
return 0;
}
九.vector的数据结构
参考《C++ primer》、《STL源码剖析》等。