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
{
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
迭代器可以进行如= == != ++ --等运算符的重载
迭代器有五种:
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
具体作用隐藏数据结构具体操作具体算法等的细节,避免部分错误操作
以上多种迭代器均继承于iterator
输出迭代器 左值 只写
如下演示一个输出迭代器应用
空结构体,标识是什么迭代器
std::iterator
依次是输入迭代器,只是一个空结构体用来标识是什么迭代器,没有任何功能
父类功能之迭代器的类型推导
std::cout << typeid(std::iterator
typeid推导类型 ::以后引用父类功能
父类功能之 迭代器指向的真实的值的类型,即<>中的第二个参数也就是真实的值
std::cout << typeid(std::iterator
迭代器指向的真实的值的类型的指针
std::cout << typeid(std::iterator
迭代器指向的真实的值的引用,虽然打印结果是值类型
std::cout << typeid(std::iterator
指针之间的差值,打印的是int 比如arr[] = {1,2,3,4} arr[2] - arr[1] = 1 内存大小的是4,但是体现出来是1,也就是一个int的大小
std::cout << typeid(std::iterator
std::iterator
std::iterator
std::cout << objValueA << "\t" << *pobjValueA << std::endl; 打印发现两个都是100
std::iterator
pObj = 200; 此时修改值
std::cout << objValueA << "\t" << pObj << std::endl; 发现打印200
std::iterator
std::iterator
打印4,即4个int长度
std::cout << pobjValueA << std::endl; 打印地址
std::cout << pobjValueB << std::endl;
std::cout << diffValue << std::endl; 打印4个int