1.vector的介绍和使用
1.1vector的介绍
vector的介绍文档:cplusplus.com/reference/vector/vector/
使用STL的三个境界:能用,明理,能扩展、那么我们接下来就学习vector,我们也将按照这个方法来学习。
1.2vector的使用
在学习vector得我时候我们需要对应着相应的文档来学习:cplusplus.com/reference/vector/vector/
vector在实际中非常的重要,在实际中我们熟悉一些常见的接口就可以了,下面我们列出了一些常见的接口 :
大部分函数接口都插入有超链接
1.2.1vector的定义
construct(构造函数声明) | 接口说明 |
vector()(重点) | 无参数构造 |
被vector(size_type n, const vaule_type& val = value_type()) | 构造并初始化n个val |
vector(const vector& x)(重点) | 拷贝构造 |
vector(InputIterator first, InputIterator last) | 使用迭代器进行初始化构造 |
以下为相应的测试函数,感兴趣的小伙伴可以 自己去验证一下:
int TestVector1()
{// constructors used in the same order as described above:vector<int> first; // empty vector of intsvector<int> second(4, 100); // four ints with value 100vector<int> third(second.begin(), second.end()); // iterating through secondvector<int> fourth(third); // a copy of third// 下面涉及迭代器初始化的部分,我们学习完迭代器再来看这部分// the iterator constructor can also be used to construct from arrays:int myints[] = { 16,2,77,29 };vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));cout << "The contents of fifth are:";for (vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)cout << ' ' << *it;cout << '\n';return 0;
}
1.2.2vector iterator的使用
iterator的使用 | 接口说明 |
begin+end(重点) | 获取第一个数据的位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator |
rbegin()+rend() | 获取第一个数据的位置的reverae_iterator, 获取最后一个位置的下一个位置的reverse_literator |
vector的迭代器使用代码演示:
void PrintVector(const vector<int>& v)
{// const对象使用const迭代器进行遍历打印vector<int>::const_iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;
}void TestVector2()
{// 使用push_back插入4个数据vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);// 使用迭代器进行遍历打印vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;// 使用迭代器进行修改it = v.begin();while (it != v.end()){*it *= 2;++it;}// 使用反向迭代器进行遍历再打印// vector<int>::reverse_iterator rit = v.rbegin();auto rit = v.rbegin();while (rit != v.rend()){cout << *rit << " ";++rit;}cout << endl;PrintVector(v);
}
1.2.3vector的空间增长问题
容量空间 | 接口说明 |
size | 获取数据的个数 |
capacity | 获取容器此时的容量 |
empty | 判断此时容器是否为空 |
resize(重点) | 改变vector的size |
reserve(重点) | 改变vector的capacity |
- capacity的代码在vs和g++下分别运行会发现,vs下的capacity是按照1.5倍增长的,g++时按照2倍增长的。这个问题就经常被考察,不要固化的认为,vector就是以两倍进行增容的,具体增长多少是根据具体的需求进行定义的。vs时PJ版本的STL,g++时SGI版本的STL.
- reverse只负责派皮空间,如果确定知道需要多少的空间,reserve·可以缓解vector增容的代价缺陷问题。
- resize在开辟空间的时候还会进行初始化,影响size;
测试函数:
// vector的resize 和 reserve// reisze(size_t n, const T& data = T())
// 将有效元素个数设置为n个,如果时增多时,增多的元素使用data进行填充
// 注意:resize在增多元素个数时可能会扩容
void TestVector3()
{vector<int> v;// set some initial content:for (int i = 1; i < 10; i++)v.push_back(i);v.resize(5);v.resize(8, 100);v.resize(12);cout << "v contains:";for (size_t i = 0; i < v.size(); i++)cout << ' ' << v[i];cout << '\n';
}// 测试vector的默认扩容机制
// vs:按照1.5倍方式扩容
// linux:按照2倍方式扩容
void TestVectorExpand()
{size_t sz;vector<int> v;sz = v.capacity();cout << "making v grow:\n";for (int i = 0; i < 100; ++i) {v.push_back(i);if (sz != v.capacity()) {sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}// 往vecotr中插入元素时,如果大概已经知道要存放多少个元素
// 可以通过reserve方法提前将容量设置好,避免边插入边扩容效率低
void TestVectorExpandOP()
{vector<int> v;size_t sz = v.capacity();v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容cout << "making bar grow:\n";for (int i = 0; i < 100; ++i) {v.push_back(i);if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}
1.2.3vector增删查改
vector增删查改 | 接口说明 |
push_back(重点) | 尾插 |
pop_back(重点) | 尾删 |
find | 查找(注意这个是算法模块实现的不是vector的成员接口) |
insert | 在position位置插入val |
erase | 删除position位置的数据 |
swap | 交换两个vector的数据空间 |
operator[](重点) | 像数组那样访问数据 |
vector容器的增删查改代码演示:
// vector的增删改查// 尾插和尾删:push_back/pop_back
void TestVector4()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);auto it = v.begin();while (it != v.end()) {cout << *it << " ";++it;}cout << endl;v.pop_back();v.pop_back();it = v.begin();while (it != v.end()) {cout << *it << " ";++it;}cout << endl;
}// 任意位置插入:insert和erase,以及查找find
// 注意find不是vector自身提供的方法,是STL提供的算法
void TestVector5()
{// 使用列表方式初始化,C++11新语法vector<int> v{ 1, 2, 3, 4 };// 在指定位置前插入值为val的元素,比如:3之前插入30,如果没有则不插入// 1. 先使用find查找3所在位置// 注意:vector没有提供find方法,如果要查找只能使用STL提供的全局findauto pos = find(v.begin(), v.end(), 3);if (pos != v.end()){// 2. 在pos位置之前插入30v.insert(pos, 30);}vector<int>::iterator it = v.begin();while (it != v.end()) {cout << *it << " ";++it;}cout << endl;pos = find(v.begin(), v.end(), 3);// 删除pos位置的数据v.erase(pos);it = v.begin();while (it != v.end()) {cout << *it << " ";++it;}cout << endl;
}// operator[]+index 和 C++11中vector的新式for+auto的遍历
// vector使用这两种遍历方式是比较便捷的。
void TestVector6()
{vector<int> v{ 1, 2, 3, 4 };// 通过[]读写第0个位置。v[0] = 10;cout << v[0] << endl;// 1. 使用for+[]小标方式遍历for (size_t i = 0; i < v.size(); ++i)cout << v[i] << " ";cout << endl;vector<int> swapv;swapv.swap(v);cout << "v data:";for (size_t i = 0; i < v.size(); ++i)cout << v[i] << " ";cout << endl;// 2. 使用迭代器遍历cout << "swapv data:";auto it = swapv.begin();while (it != swapv.end()){cout << *it << " ";++it;}// 3. 使用范围for遍历for (auto x : v)cout << x << " ";cout << endl;
}