STL提供了一组表示容器 迭代器 函数对象 和算法的模板。容器是一个与数组类似的单元,可以存储若干个值。STL容器是同质的,即存储的值的类型相同;算法是完成特定任务(如对数组进行排序 又或 在链表中查找特定值)的处方;迭代器能够用来遍历容器的对象,与能够遍历数组的指针类似,是广义指针;函数对象是类似函数的对象,可以是类对象或函数指针。STL使得能够构造各种容器(数组 队列 链表等)和执行各种操作(包括搜索 排序和随机排列)
STL并不是面向对象的编程,而是一种不同的编程模式-泛型编程,当然我们用一言两句可能说不清,我们可以通过一些实际应用真是了解到容器 迭代器 算法等
vector
先来说说这个容器,vector是动态数组 我们在定义数组时候必须确定其大小 而动态数组就不需要考虑这种情况,只有在我们需要的时候,将元素插入到里面,并不需要定义容器的大小。要使类成为通用的,应将它设计为模板类,STL在头文件<\vector>中定义了一个vector模板
要创建<\vector>模板对象,可使用通常的<\type>表示法来指出所要使用的类型 另外vector模板支持动态内存分配 因此可以用初始化参数来指出需要多少元素
代码演示一下
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> arry_int(5);//创建一个vector容器,并且在里面放了5个int元素
int n;
cin >> n;
vector<double> source(n);//创建一个vector容器,并且在里面放了5个double元素
arry_int[0] = 9;
for (size_t i = 0; i < n; i++)
{
cout << source[i] << endl;
cout << arry_int[i] << endl;
}
}
C++
与string类相似,各种STL容器模板都接受一个可选的模板参数 该参数指定使用哪个分配器对象来管理内存。例如 vector模板的开头与下面类似
template<\class T,class Allocator = allocator<\T>>
class vector{…}
如果省略该参数模板的值,则容器模板将默认使用allocator<\T>类。这个类使用new和delete
我们可以根据文档给出的构造函数来一一实现一下 文档地址:https://cplusplus.com/reference/vector/vector/vector/
// constructing vectors
#include <iostream>
#include <vector>
int main ()
{
// constructors used in the same order as described above:
std::vector<int> first; // empty vector of ints
std::vector<int> second (4,100); // four ints with value 100
std::vector<int> third (second.begin(),second.end()); // iterating through second
std::vector<int> fourth (third); // a copy of third
// the iterator constructor can also be used to construct from arrays:
int myints[] = {16,2,77,29};
std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
std::cout << "The contents of fifth are:";
for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
C++这就是vector的类初始化(构造函数)
vector的更多操作
除了分配空间,vector还提供了很多方法 如
size() 返回容器中的元素数目 swap()交换两个容器的内容 begin()返回一个指向容器的第一个元素的迭代器 end()返回一个表示超过容器尾的迭代器
这里就需要说明一下什么是迭代器。
他是一个广义的指针,事实上,它可以是指针,也可以是一个可对其执行类似指针的操作 如解除引用和递增的对象 稍后将知道,通过将指针广义化为迭代器 让STL能够为各种不同的容器类提供统一的接口,每个容器类都定义了一个合适的迭代器
我们可以这样定义一个迭代器 vector<\double>::iterator pd;
我们创建一个容器对象 vector<\int> age;
可以这样 pd = age.begin(); 当然C++提供了自动类型推断很有用的地方 例如
auto pd = age.begin(); 通过容器和迭代器我们可以遍历容器中的内容
vector<int> arry_int(5);//创建一个vector容器,并且在里面放了5个元素
arry_int[0] = 9;
vector<int>::iterator pd;
pd = arry_int.begin();
for (arry_int.begin() ; pd!=arry_int.end() ; pd++)
{
cout << *pd << endl;
}
C++push_back() 将元素添加到动态数组尾部 使之能够容纳新的成员 即可以
vector<double> source;
double temp;
while (cin>>temp&&temp>=0)
{
source.push_back(temp);
}
cout << "you entered " << source.size() << "sources.\n";
C++每次循环都给source增加一个元素,在实际运用的过程中无需知道元素的数目,只要内存足够,元素可以一直增加
erase()可以删除指定区间的元素 第一个参数表示删除的起始迭代器 第二个参数表示删除的结束迭代器比如我们要删除第一个元素和第二个元素 即source.erase(source.begin(),source.begin()+1);
insert() 有三个参数 第一个参数指定了新元素的插入位置 第二个和第三个参数指定了被插入的区间 第二个参数和第三个参数一般是另一个容器对象
①、arr_int.erase(v.begin()+k); //删除 arr_int 动态数组的下标为 k 的元素,返回下一个位置的迭代器
②、arr_int.erase(v.begin()+l, v.end()-r); //删除 arr_int 动态数组中下标 [\l,v.end()-r) 的元素source.insert(source.begin,source_new.begin()+1,source_new.end());
①、调用 insert 在下标为1的前面插入一个元素,arr_int.insert(arr_int.begin()+1, 888);
②、调用 insert 在下标为2的前面插入3个888元素,arr_int.insert(arr_int.begin()+2, 3, 888);
③、调用 insert 在下标为2的前面插入N个元素:
除了上述说到的操作还有其他操作列在下方
vector<int> arr_int;
① arr_int[idx] 或 arr_int.at(idx) //返回动态数组中下标为 idx 的 arr_int[idx] 元素的值
② arr_int.size(); //返回 arr_int 数组元素的总个数
③ arr_int.front(); //返回 arr_int 数组的第一个元素的值
④ arr_int.back(); //返回 arr_int 数组的最后一个元素的值
⑤ arr_int.clear(); //清空 arr_int 数组,即把里面的所有元素都删除
⑥ arr_int.begin(); //返回 arr_int 数组第一个数的下标
⑦ arr_int.end(); //返回 arr_int 数组最后一个数的下标
⑧ arr_int.empty(); //判断 arr_int 数组是否为空,如果为空则返回true,非空(有元素)则返回false
⑨ arr_int.swap(v1); //v1是另一个动态数组,将 arr_int 和 v1 两个动态数组的元素互换
⑩ swap(arr_int, v1); //同⑨
C++