STL:标准模板库,具有代码高复用性,强大的功能,性能高效以及开源可跨平台
代码分支:? ?
1.HP?STL,第一个C++版本,惠普STL
2.P.J.Plauger STL,VS IDE使用
3.Rouge Wave STL,C++ Builder IDE使用
4.STLport 常用于个人项目
5. SGI STL? GCC IDE使用
STL组件
1.迭代器 iterator 本质是一种泛型指针
2.容器 Container
3.算法 algorithm
4.仿函数 functor 本质类模板
5.适配器 adaoter
6.空间适配器 allocator 本质类模板
例一:
int arr[5] = {2, 6, 8, 7, 9};
如下两个函数
函数一:打印数组选定位置的元素
void print(int * begin, int * end) 传入调用数组的起始位置和结束位置
{
? ? while(begin != end)
????????{
? ? ? ? ? ? std::cout << *begin++ << "\t"; 后置加加,先解引用后续地址后移
????????}
? ? ? ? std::cout << std::endl;
)
print(arr, arr + 5);
例二
struct Node 创建一个链表结构体
{
? ? int data;
? ? Node* next;
}
Node* info;?声明了一个名为info
的指针,该指针指向一个Node
类型的对象。
Node* infoend;
void CreateList(int *nArr, int nCount) 利用数组创建链表 参数为数组及节点个数
{
? ? info = new Node;
? ? info->data = nArr[0];
? ? info->next = nullptr;
? ? Node *temp = info; 创建一个临时头节点
? ? for(size_t i = 1; i < nCount; i++)
? ? {
? ? ? ? temp->next = new Node;
? ? ? ? temp = temp->next;
? ? ? ? temp->data = nArr[i];
? ? ? ? temp->next = nullptr;
? ? ? ? inforend = temp;
? ? }
}
void print(Node* begin, Node * end)
{
? ? while (begin != end)
? ? {
? ? ? ? std::cout << begin->data << "\t";
? ? ? ? begin = begin->next;
? ? }
}
CreateList(arr, 5);
print(info, infoend->end)
以下创建一个模板,使它可以同时应用上述那种函数
template(typename T)
void print(T begin, T end) 创建一个模板函数
{
? ? for(T i?= 0; i != end; ++i)传入Node时,节点++不一定能取到下一个,因为链式结构
? ? (
? ? ? ? std::cout << *i?<< "\t"; 从Node节点地址上,获取不了数据
? ? )
}
CreatList(arr, 5);
print(arr, arr + 5);以数组作为参数,可以运行
print(info, infoend->next); 以链表作为参数,不可以运行
此时重载一个输出,使其可以输入链表节点数据
std:: ostream & operator <<(std::ostream &cout,?const Node & node) 传入一个输出流和一个节点
{
? ? cout << node.data;
? ? return cout;
}
此时仍然会有乱码,原因解引用无法获取节点的数据且++不一定获得下一个节点因为链式结构?
解决方法写一个特化,本质是就是函数重载,没有复用
template<>
void print<Node*>(Node*?begin, Node*?end)
{
? ? while(begin != end)
? ? {
? ? ? ? std::cout << begin->data << "\t";
? ? ? ? begin = begin->next;
? ? }
}
print(info, infoend->next);
上述模板过于复杂,并没有实现高复用大的作用,所以以下使用迭代器,在中间层做一个中转:
class ListIterator 一个list迭代器,需要在最初的模板!= ++ *进行重载
{
public:
? ? Node * pNode;
? ? ListIterator(Node * p):pNode(p){}; 对内部pNode进行初始化赋值?
? ? ListIterator & operator++() 重载的是前置++
? ? {
? ? ? ? pNode = pNode->next;
? ? ? ? 在外部操作的时候实际是用ListIterator obj进行操作,而不是Node的节点,obj进入自己的重载函数中进行操作内部的节点,也就是说类对象是一个中转器
? ? ? ? return *this;
? ? }? ? ? ?
? ? ?bool operator?!= (ListIterator &li)
? ? {
? ? ? ? return pNode != li.pNode; 对比两个迭代器中pNode是否一样
? ? }
? ? Node&?operator * ()
? ? {
? ? ? ? return *pNode;
? ? }
}
ListIterator begin(info);
ListIterator end(infoend);
print(begin, end) 传入节点
需要包含#include <iterator>
迭代器可以进行如= == != ++ --等运算符的重载
迭代器有五种:
1.输出迭代器 独立 支持 = == != ++i i++ 自身是右值 只读的?
2.输入迭代器? 支持 = == != ++i i++ 自身是左值 只写的
3.前向迭代器 包含2 支持 = == != ++i i++? 可读可写
4.双向迭代器 包含3 支持 = == != ++i i++ --i i++ 可读可写?
5.随机访问迭代器 包含4 支持= == != ++p?p++ --p p-- p+i p-i p[i] p<p1判断p在p1的前后? p>p1 判断p1在p的前面
具体作用隐藏数据结构具体操作具体算法等的细节,避免部分错误操作
以上多种迭代器均继承于iterator
输出迭代器? 左值 只写
如下演示一个输出迭代器应用
?? ?空结构体,标识是什么迭代器
?? ?std::iterator<std::input_iterator_tag , int>obj;
依次是输入迭代器,只是一个空结构体用来标识是什么迭代器,没有任何功能
? ? 父类功能之迭代器的类型推导
?? ?std::cout << typeid(std::iterator<std::input_iterator_tag, int>::iterator_category).name() << std::endl;
typeid推导类型? ::以后引用父类功能
?? 父类功能之?迭代器指向的真实的值的类型,即<>中的第二个参数也就是真实的值
?? ?std::cout << typeid(std::iterator<std::input_iterator_tag, int>::value_type).name() << std::endl;
?? ?迭代器指向的真实的值的类型的指针
?? ?std::cout << typeid(std::iterator<std::input_iterator_tag, int>::pointer).name() << std::endl;
? ?迭代器指向的真实的值的引用,虽然打印结果是值类型?
?? ?std::cout << typeid(std::iterator<std::input_iterator_tag, int>::reference).name() << std::endl;
?? ?指针之间的差值,打印的是int? 比如arr[] = {1,2,3,4} arr[2] - arr[1] = 1 内存大小的是4,但是体现出来是1,也就是一个int的大小
? ? std::cout << typeid(std::iterator<std::input_iterator_tag, int>::difference_type).name() << std::endl;
?? ?std::iterator<std::input_iterator_tag, int>::value_type objValueA = 100;?相当于 int a = 100
?
?? ?std::iterator<std::input_iterator_tag, int>::pointer pobjValueA = &objValueA;?相当于int * pA = &a;
?? ?std::cout << objValueA << "\t" << *pobjValueA << std::endl; 打印发现两个都是100
?? ?std::iterator<std::input_iterator_tag, int>::reference pObj = objValueA; 引用指向objValue
?? ?pObj = 200; 此时修改值
?? ?std::cout << objValueA << "\t" << pObj << std::endl; 发现打印200
?? ?std::iterator<std::input_iterator_tag, int>::pointer pobjValueB = &objValueA + 4;
?? ?std::iterator<std::input_iterator_tag, int>::difference_type diffValue = pobjValueB - pobjValueA;
? ? 打印4,即4个int长度
?? ?std::cout << pobjValueA << std::endl; 打印地址
?? ?std::cout << pobjValueB << std::endl;
?? ?std::cout << diffValue << std::endl; 打印4个int
?