STL标准库(一)STL迭代器

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* 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

迭代器可以进行如= == != ++ --等运算符的重载

迭代器有五种:

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] pp1 判断p1在p的前面

具体作用隐藏数据结构具体操作具体算法等的细节,避免部分错误操作

以上多种迭代器均继承于iterator

输出迭代器  左值 只写

如下演示一个输出迭代器应用


    空结构体,标识是什么迭代器
    std::iteratorobj;

依次是输入迭代器,只是一个空结构体用来标识是什么迭代器,没有任何功能
    父类功能之迭代器的类型推导
    std::cout << typeid(std::iterator::iterator_category).name() << std::endl;

typeid推导类型  ::以后引用父类功能
   父类功能之 迭代器指向的真实的值的类型,即<>中的第二个参数也就是真实的值
    std::cout << typeid(std::iterator::value_type).name() << std::endl;
    迭代器指向的真实的值的类型的指针
    std::cout << typeid(std::iterator::pointer).name() << std::endl;
   迭代器指向的真实的值的引用,虽然打印结果是值类型 
    std::cout << typeid(std::iterator::reference).name() << std::endl;
    指针之间的差值,打印的是int  比如arr[] = {1,2,3,4} arr[2] - arr[1] = 1 内存大小的是4,但是体现出来是1,也就是一个int的大小

    std::cout << typeid(std::iterator::difference_type).name() << std::endl;
    std::iterator::value_type objValueA = 100; 相当于 int a = 100
 
    std::iterator::pointer pobjValueA = &objValueA; 相当于int * pA = &a;
    std::cout << objValueA << "\t" << *pobjValueA << std::endl; 打印发现两个都是100
    std::iterator::reference pObj = objValueA; 引用指向objValue
    pObj = 200; 此时修改值
    std::cout << objValueA << "\t" << pObj << std::endl; 发现打印200
    std::iterator::pointer pobjValueB = &objValueA + 4;
    std::iterator::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
 

你可能感兴趣的:(c++,开发语言)