
 纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。
💬文章目录
- 一.vector容器基本概念
- 二.vector常用操作
- ①vector构造函数
- ②特性操作
- ③元素操作
- ④赋值操作
- ⑤交换操作
- ⑥比较操作
- ⑦插入和删除操作
 
 
一.vector容器基本概念
vector的数据安排以及操作方式,与array非常相似,都是一片连续的储存空间,两者的唯一差别在于空间的运用的灵活性。
array是静态数组,一旦配置了空间就无法再改变,要换大一点或者小一点的空间,可以,一切琐碎得由自己来,首先配置一块新的空间,然后将旧空间的数据搬往新空间,再释放原来的空间。
vector是动态空间(动态数组),随着元素的加入,它的内部机制会自动扩充空间以容纳新元素。因此vector的运用对于内存的合理利用与运用的灵活性有很大的帮助,我们再也不必害怕空间不足而一开始就要求一个大块头的array了。

①vector的实现技术:
 vector的实现技术,关键在于其对大小的控制以及重新配置时的数据移动效率,一旦vector旧空间满了,如果客户每新增一个元素,vector内部只是扩充一个元素的空间,实为不智,因为只要是扩充空间(不论多大),其步骤就是“配置新空间-数据移动-释放旧空间”的大工程,时间成本很高,所以为了降低空间配置时的速度成本,vector实际配置的大小可能比客户端需求大一些,以备将来可能的扩充,这边是容量的概念。换句话说,一个vector的容量永远大于或等于其大小,一旦容量等于大小,便是满载,下次再有新增元素,整个vector容器就得另觅居所(配置新空间-数据移动-释放旧空间)。
 ②vector迭代器:
 vector维护一个线性空间,所以不论元素的型别如何,普通指针都可以作为vector的迭代器,因为vector迭代器所需要的操作行为,如operaroe*, operator->, operator++, operator–, operator+, operator-, operator+=, operator-=, 普通指针天生具备。vector支持随机存取,而普通指针正有着这样的能力。所以vector提供的是随机访问迭代器(Random Access Iterators).
 ③vector的数据结构:
 vector所采用的数据结构非常简单,线性连续空间,它以两个迭代器_Myfirst和_Mylast分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器_Myend指向整块连续内存空间的尾端。
 ④注意:
所谓动态增加大小,并不是在原空间之后续接新空间(因为无法保证原空间之后尚有可配置的空间),而是分配一块更大的内存空间,然后将原数据拷贝新空间,并释放原空间。因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就都失效了。这是程序员容易犯的一个错误,务必小心。
二.vector常用操作
①vector构造函数
注:使用vector容器时,需包含头文件#include < vector>
| 函数 | 解释 | 
|---|---|
| vector< T > v; | 采用模板实现类实现(显示实例化),默认构造函数, | 
| vector(v.begin(), v.end()); | 将v[begin(), end())区间中的元素拷贝给本身 | 
| vector(n, elem); | 构造函数将n个elem拷贝给本身。 | 
| vector(const vector &vec); | 拷贝构造函数,拿另一个vector对象初始化本身 | 
实例:vector构造函数
#include <iostream> 
#include<vector> 
using namespace std;
void printvector(const vector<int>& vec)
{
    for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it)
    {
        cout << *it;
    }
    cout << endl;
}
int main()
{
    vector<int> v1 = { 1,2,3 };//采用模板实现类实现(显示实例化),默认构造函数,
    vector<int> v2(6,1);//构造函数将n个elem拷贝给本身。
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    vector<int> v3(arr, arr+sizeof(arr)/ sizeof(arr[0]));//将v[begin(), end())区间中的元素拷贝给本身
    vector<int> v4(v1);//拷贝构造函数,拿另一个vector对象初始化本身
    printvector(v1);
    printvector(v2);
    printvector(v3);
    printvector(v4);
    return 0;
}

②特性操作
| 函数原型 | 解释 | 
|---|---|
| size_t max_size() const; | 返回容器的最大长度 | 
| size_t capacity() const; | 返回容器的容量。 | 
| size_t size() const; | 返回容器的实际大小(已使用的空间)。 | 
| bool empty() const; | 判断容器是否为空。 | 
| void clear(); | 清空容器。 | 
| void reserve(size_t size); | 容器预留size个元素长度,预留位置不初始化,元素不可访问,作用:预开辟空间,避免多次重新分配空间 | 
| void shrink_to_fit(); | 将容器的容量降到实际大小(需要重新分配内存)。 | 
| void resize(size_t size); | 把容器的实际大小置为size,如果size<实际大小,会截断多出的部分;如果size>实际大小,则以默认值0填充新位置 | 
| void resize(size_t size,const T &value); | 把容器的实际大小置为size,如果size<实际大小,会截断多出的部分;如果size>实际大小,就用value填充。 | 
实例:reserve和resize辨析:
#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;
}
void test()
{
    //1.resize开辟空间,并初始化
	//2.reserve开辟空间,但不初始化
	vector<int> v2;
	v2.push_back(1);//尾部插入一个元素
	v2.push_back(2);
	v2.push_back(3);
	cout << "size:" << v2.size() << endl;
	v2.resize(5);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
	cout << "size:" << v2.size() << endl;
	printvector(v2);
	v2.resize(2);//如果容器变短,则末尾超出容器长度的元素被删除。
	cout << "size:" << v2.size() << endl;
	printvector(v2);
	v2.resize(5,6);//如果容器变长,也可以用value填充
	cout << "size:" << v2.size() << endl;
	printvector(v2);
	v2.reserve(20);
	v2.push_back(20);
	printvector(v2);//容器变长了,但并没有初始化
	cout << "size:" << v2.size() << endl;
	cout << "capacity:" << v2.capacity() << endl;
	//cout << v2[10] << endl;//err,不能访问未初始化的空间
}
int main()
{
	test();
	return 0;
}

reserve作用:预开辟空间,避免多次重新分配空间
 如果不加reserve预开辟空间,我们看看会重新分配多少次空间。
#include <iostream> 
#include<vector> 
using namespace std;
void test()
{
    vector<int> v;
	int* p = NULL;
	int num = 0;
	for (int i = 0; i < 10001000; i++)
	{
		v.push_back(i);
		if (p != &v[0])
		{
			p = &v[0];
			num++;
		}
	}
	cout << "num=" << num << endl;
	return 0;
}
int main()
{
	test();
	return 0;
}

 加上v.reserve(10001000);
 
③元素操作
| 函数原型 | 解释 | 
|---|---|
| T &operator[](size_t n); | 通过[]访问元素,如果越界,不抛异常,程序直接挂掉 | 
| T &at(size_t n); | 通过at方法获取下标为n的元素,如果n越界,抛出out_of_range异常。 | 
| T *data(); | 返回容器中动态数组的首地址。 | 
| const T *data() const; | 返回容器中动态数组的首地址。 | 
| T &front(); | 返回第一个元素。 | 
| T &back(); | 返回,最后一个元素。 | 
④赋值操作
作用:通过重载赋值运算符operator=和成员函数assign(),给已存在的容器赋值,将覆盖容器中原有的内容。
| 函数原型 | 解释 | 
|---|---|
| vector &operator=(const vector &v); | 把容器v赋值给当前容器。 | 
| assign(beg, end); | 将[beg, end)区间中的数据拷贝赋值给本身。 | 
| void assign(const size_t n, const T& value); ; | 将n个value拷贝赋值给本身。 | 
| void assign(const size_t n, const T& value); | 把n个value给容器赋值。 | 
⑤交换操作
💬表格一览:
| 函数原型 | 解释 | 
|---|---|
| void swap(vector &v); | 把当前容器与v交换。交换的是动态数组的地址。作品:收缩内存空间。 | 
swap妙用:收缩内存空间
#include <iostream> 
#include<vector> 
using namespace std;
void test()
{
    vector<int> v;
	for (int i = 0; i < 100000; i++)
	{
		v.push_back(i);
	}
	cout << "v的容量:" << v.capacity() << endl;
	cout << "v的实际大小:" << v.size() << endl;
	cout << "----------------" << endl;
	v.resize(10);//将容器的实际大小设置为10,但容量没变
	cout << "resize后v的容量:" << v.capacity() << endl;
	cout << "resize后v的实际大小:" << v.size() << endl;
	cout << "----------------" << endl;
	vector<int>(v).swap(v);//匿名对象和v对象交换
	//匿名对象调用拷贝构造,匿名对象的容量和实际大小均为10,此时在与v进行交换,做到了收缩内存的目的
	cout << "与匿名对象交换后v的容量:" << v.capacity() << endl;
	cout << "与匿名对象交换后v的实际大小:" << v.size() << endl;
}
int main()
{
	test();
	return 0;
}

⑥比较操作
💬表格一览:
| 函数原型 | 解释 | 
|---|---|
| bool operator == (const vector< T > & v) const; | |
| bool operator != (const vector< T > & v) const; | 
⑦插入和删除操作
💬表格一览:
| 函数原型 | 解释 | 
|---|---|
| iterator insert(iterator pos, const T& ele); | 在指定位置插入一个元素ele 返回指向插入元素的迭代器。 | 
| iterator insert(const_iterator pos, int count,ele); | 迭代器指向位置pos插入count个元素ele.返回指向插入元素的迭代器。 | 
| void push_back(const T& ele); | 尾部插入元素ele | 
| void pop_back(); | 删除最后一个元素 | 
| iterator erase(const_iterator start, const_iterator end); | 删除迭代器从start到end之间的元素,返回下一个有效的迭代器。 | 
| iterator erase(const_iterator pos); | 删除迭代器指向的元素,返回下一个有效的迭代器。 | 
实例:vector插入和删除操作
#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;
}
void test()
{
    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
}
int main()
{
    test();
	return 0;
}




















