STL标准库(一)STL迭代器

发布时间:2024年01月05日

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
?

文章来源:https://blog.csdn.net/2301_78838647/article/details/135042480
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。