目录
vector类的介绍:
vector是C++标准模板库中的部分内容,中文偶尔译作“容器”,但并不准确。它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
实质上vector的作用等同于数据结构当中的顺序表。因为vector是使用模板实现的,所以我们可以通过传入指定的参数,进行存储各种类型的数据。
vector类的构造函数:
和我们平时定义的类一样,vector同样有很多构造函数,用于创建我们的顺序表。构造函数如下:
其中有一个参数大家可能会很陌生:const allocator_type& alloc = allocator_type(),该参数表示的是使用默认的内存分配器为系统默认的分配器。我们可以将其忽略,直接将第一个参数为空参数。即创建一个顺序表,但是顺序表当中的数据为空。
第二个构造函数作用是开辟n个数据的空间,空间的类型默认情况下和我们前面定义好的类型相同。
第三个构造函数时使用一个迭代器创建一个顺序表。我们甚至可以创建一个数组,传入数组的指针作为实例化的参数,进行创建vector的对象。
最后一个是vector类的构造函数,我们可以使用一个创建好的vector对象进而创建一个一模一样的vector对象。测试代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
using namespace std;
int main()
{
//调用第一个默认参数为空的构造函数
vector<int> test1;
//调用第二个构造函数,为其分配四个空间
vector<int> test2(4);
//使用指针初识一个vector对象
int arr[] = {1,2,3,4,5,6};
vector<int> test3(arr, arr + 6); //左开右闭区间
vector<int> test3_2 = { 11,22,33,44 }; //实质上也是调用迭代器初始化vector对象
//使用拷贝构造初始化一个vector对象
vector<int> test4(test3);
return 0;
}
operator=
自定义函数要想使用使用常规的操作符执行相应的操作就需要自己重载相应的操作符。在vector类当中为了方便我们使用,特地重载了赋值操作符=。实质上是调用了我们上面构造函数当中的拷贝构造。测试代码如下:
//创建两个vector对象,使用赋值操作符修改指定对象
vector<int> test1 = { 1,2,3,4 };
cout << "修改之前的test1对象:";
for (auto e : test1)
{
cout << e << " ";
}
cout << endl;
vector<int> test2 = { 11,22,33,44 };
test1 = test2;
cout << "修改之后的test1对象:";
for (auto e : test1)
{
cout << e << " ";
}
operator [ ]
作为一个顺序表来说,顺序表最大的优势就是可以使用 [ ] 进行指定数据的访问。(数据存储是连续的)所以在vector类当中同样实现了该功能,同样是使用了函数重载的形式实现。使用代码如下:
//创建一个vector对象,使用[]进行数组的遍历
vector<int> test = { 1,2,3,4,5 };
int i = 0;
for (i = 0; i < test.size(); i++)
{
cout << test[i] << " ";
}
begin & end
这一对函数的使用方式和我们之前的string相同,同样是为我们的迭代器进行服务的。我们不仅可以通过迭代器进行顺序表的遍历还可以调用 std 库当中的各种函数进行指定的操作,例如逆序,排序操作。其中begin实质上代表的就是顺序表第一个元素的指针,end表示的就是顺序表的尾指针的下一个位置。使用代码如下:
//创建一个vector对象,使用begin和end对vector对象进行指定的处理
vector<int> test = { 12,2,11,24,77,34,28 };
//首先利用迭代器对顺序表进行遍历
std::vector<int>::iterator it = test.begin();
while (it != test.end())
{
cout << *it << " ";
it++;
}
cout << endl;
//使用algorithm库当中的sort函数对顺序表当中的数据进行排序
sort(test.begin(), test.end());
it = test.begin();
while (it != test.end())
{
cout << *it << " ";
it++;
}
cout << endl;
//使用std库当中的reverse函数对排序好的顺序表进行逆序操作
reverse(test.begin(), test.end());
it = test.begin();
while (it != test.end())
{
cout << *it << " ";
it++;
}
cout << endl;
size & resize
size是vector对象的一个重要的参数,其表示的是顺序表当中的数据的个数。我们可以通过调用这个函数来查看顺序表当中的数据的个数进而尽心相应的操作。resize的作用是调整顺序表元素的个数。我们可以通过resize开辟相应的数组的空间,并将顺序表进行赋初值。代码如下:
//通过size函数作为结束条件打印顺序表
vector<int> test = { 1,2,3,4,5 };
int i = 0;
while (i < test.size())
{
cout << test[i] << " ";
i++;
}
cout << endl;
//通过resize函数设置size的大小,并为新的空间进行赋初值
test.resize(8, 0);
i = 0;
while (i < test.size())
{
cout << test[i] << " ";
i++;
}
capacity & reserve
和size相对应的就是capacity函数了。capacity的作用就是返回当前顺序表的容量。容量和顺序表的大小有很大的区别,容量必须大于或者等于数据的大小。只有这样才能保证我们的数据不越界。同样的我们可以通过reserve进行修改我们顺序表的容量。(调整我们开辟的空间进行修改)测试代码如下:
//通过调用capacity函数观察顺序表的大小
vector<int> test = { 1,2,3,4,5,6 };
cout << "顺序表数据的大小:" << test.size() << " " << "顺序表的容量" << test.capacity() << endl;
test.reserve(22);
cout << "顺序表数据的大小:" << test.size() << " " << "顺序表的容量" << test.capacity() << endl;
push_back & pop_back
在我们之前对顺序表的书写当中我们会发现:对于顺序表最便利的就是尾插,不需要进行数据的挪动,其他位置都需要或多或少的移动数据的位置。所以为了针对顺序表的这一特性,系统当中还设置了尾插和尾删函数。我们可以通过调用函数对顺序表进行指定的修改。测试代码如下:
//调用尾插函数和尾删函数对顺序表进行指定的操作
vector<int> test = { 1,2,3,4 };
//打印原顺序表
for (auto e : test)
{
cout << e << ' ';
}
cout << endl;
//插入最后的数据55
test.push_back(55);
for (auto e : test)
{
cout << e << ' ';
}
cout << endl;
//删除最后的55
test.pop_back();
for (auto e : test)
{
cout << e << ' ';
}
cout << endl;
insert & erase
对于顺序表数据的插入肯定不能只是在顺序表末尾数据的插入,当然还需要有指定位置的数据的插入和删除,所以也就有了insert函数和erase函数了。我们需要向函数当中传入指定位置的下标之后就可以进行相应的操作了。测试代码如下:
//使用insert向顺序表当中指定位置插入和删除函数
vector<int> test = { 1,2,3,4,5 };
print(test);
//在顺序表的头部插入12
test.insert(test.begin(), 12);
print(test);
//在顺序表第三个元素的位置插入55
test.insert(test.begin() + 2, 55);
print(test);
//删除顺序表当中的最后一个元素
test.erase(test.end() - 1);
print(test);
需要注意的是我们传入的插入函数的位置不能再是一个下标,而应该是一个指针。这个给指针我们可以通过begin函数加减获取。