广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >怎么解析C++ 的STL迭代器原理和实现
  • 636
分享到

怎么解析C++ 的STL迭代器原理和实现

2023-06-26 06:06:31 636人浏览 泡泡鱼
摘要

怎么解析c++ 的STL迭代器原理和实现,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1. 迭代器简介为了提高C++编程的效率,STL(Standar

怎么解析c++ 的STL迭代器原理和实现,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

1. 迭代器简介

为了提高C++编程的效率,STL(Standard Template Library)中提供了许多容器,包括vector、list、map、set等。然而有些容器(vector)可以通过下标索引的方式访问容器里面的数据,但是大部分的容器(list、map、set)不能使用这种方式访问容器中的元素。为了统一访问不同容器时的访问方式,STL为每种容器在实现的时候设计了一个内嵌的iterator类,不同的容器有自己专属的迭代器(专属迭代器负责实现对应容器访问元素的具体细节),使用迭代器来访问容器中的数据。除此之外,通过迭代器可以将容器和通用算法结合在一起,只要给予算法不同的迭代器,就可以对不同容器执行相同的操作,例如find查找函数(因为迭代器提供了统一的访问方式,这是使用迭代器带来的好处)。迭代器对一些基本操作如*、->、++、==、!=、=进行了重载,使其具有了遍历复杂数据结构的能力,其遍历机制取决于所遍历的容器,所有迭代器的使用和指针的使用非常相似。通过begin,end函数获取容器的头部和尾部迭代器,end迭代器不包含在容器之内,当begin和end返回的迭代器相同时表示容器为空。

STL主要由 容器、迭代器、算法、函数对象、和内存分配器 五大部分构成。

2. 迭代器的实现原理

首先,看看STL中迭代器的实现思路:

怎么解析C++ 的STL迭代器原理和实现

从上图中可以看出,STL通过类型别名的方式实现了对外统一;在不同的容器中类型别名的真实迭代器类型是不一样的,而且真实迭代器类型对于++、--、*、->等基本操作的实现方式也是不同的。(PS:迭代器很好地诠释了接口与实现分离的意义)

既然我们已经知道了迭代器的实现思路,现在如果让我们自己设计一个list容器的简单迭代器,应该如何实现呢?

list类需要有操作迭代器的方法

begin/end

insert/erase/emplace

list类有一个内部类list_iterator

有一个成员变量ptr指向list容器中的某个元素

iterator负责重载++、--、*、->等基本操作

list类定义内部类list_iterator的类型别名

以上就是实现一个list容器的简单迭代器需要考虑的具体细节。

3. 迭代器的简单实现

my_list.h(重要部分有注释说明

//// Created by wengle on 2020-03-14.// #ifndef CPP_PRIMER_MY_LIST_H#define CPP_PRIMER_MY_LIST_H #include <iOStream> template<typename T>class node {public:    T value;    node *next;    node() : next(nullptr) {}    node(T val, node *p = nullptr) : value(val), next(p) {}}; template<typename T>class my_list {private:    node<T> *head;    node<T> *tail;    int size; private:    class list_iterator {    private:        node<T> *ptr; //指向list容器中的某个元素的指针     public:        list_iterator(node<T> *p = nullptr) : ptr(p) {}                //重载++、--、*、->等基本操作        //返回引用,方便通过*it来修改对象        T &operator*() const {            return ptr->value;        }         node<T> *operator->() const {            return ptr;        }         list_iterator &operator++() {            ptr = ptr->next;            return *this;        }         list_iterator operator++(int) {            node<T> *tmp = ptr;            // this 是指向list_iterator的常量指针,因此*this就是list_iterator对象,前置++已经被重载过            ++(*this);            return list_iterator(tmp);        }         bool operator==(const list_iterator &t) const {            return t.ptr == this->ptr;        }         bool operator!=(const list_iterator &t) const {            return t.ptr != this->ptr;        }    }; public:    typedef list_iterator iterator; //类型别名    my_list() {        head = nullptr;        tail = nullptr;        size = 0;    }     //从链表尾部插入元素    void push_back(const T &value) {        if (head == nullptr) {            head = new node<T>(value);            tail = head;        } else {            tail->next = new node<T>(value);            tail = tail->next;        }        size++;    }     //打印链表元素    void print(std::ostream &os = std::cout) const {        for (node<T> *ptr = head; ptr != tail->next; ptr = ptr->next)            os << ptr->value << std::endl;    } public:    //操作迭代器的方法    //返回链表头部指针    iterator begin() const {        return list_iterator(head);    }     //返回链表尾部指针    iterator end() const {        return list_iterator(tail->next);    }     //其它成员函数 insert/erase/emplace}; #endif //CPP_PRIMER_MY_LIST_H

test.cpp

//// Created by wengle on 2020-03-14.//#include <string>#include "my_list.h"struct student {    std::string name;    int age;    student(std::string n, int a) : name(n), age(a) {}    //重载输出操作符    friend std::ostream &operator<<(std::ostream &os, const student &stu) {        os << stu.name << " " << stu.age;        return os;    }};int main() {    my_list<student> l;    l.push_back(student("bob", 1)); //临时量作为实参传递给push_back方法    l.push_back(student("allen", 2));    l.push_back(student("anna", 3));    l.print();    for (my_list<student>::iterator it = l.begin(); it != l.end(); it++) {        std::cout << *it << std::endl;        *it = student("wengle", 18);    }    return 0;}//// Created by wengle on 2020-03-14.// #include <string>#include "my_list.h" struct student {    std::string name;    int age;     student(std::string n, int a) : name(n), age(a) {}     //重载输出操作符    friend std::ostream &operator<<(std::ostream &os, const student &stu) {        os << stu.name << " " << stu.age;        return os;    }}; int main() {    my_list<student> l;    l.push_back(student("bob", 1)); //临时量作为实参传递给push_back方法    l.push_back(student("allen", 2));    l.push_back(student("anna", 3));    l.print();     for (my_list<student>::iterator it = l.begin(); it != l.end(); it++) {        std::cout << *it << std::endl;        *it = student("wengle", 18);    }    return 0;}

4. 迭代器失效

// inserting into a vector#include <iostream>#include <vector> int main (){  std::vector<int> myvector (3,100);  std::vector<int>::iterator it;   it = myvector.begin();  it = myvector.insert ( it , 200 );   myvector.insert (it,200,300);  //it = myvector.insert (it,200,300);  myvector.insert (it,5,500); //当程序执行到这里时,大概率会crash  for (std::vector<int>::iterator it2=myvector.begin(); it2<myvector.end(); it2++)    std::cout << ' ' << *it2;  std::cout << '\n';   return 0;}

上面的代码很好地展示了什么是迭代器失效?迭代器失效会导致什么样的问题?

当执行完myvector.insert (it,200,300);这条语句后,实际上myvector已经申请了一块新的内存空间来存放之前已保存的数据本次要插入的数据,由于it迭代器内部的指针还是指向旧内存空间的元素,一旦旧内存空间被释放,当执行myvector.insert (it,5,500);时就会crash(PS:因为你通过iterator的指针正在操作一块已经被释放的内存,大多数情况下都会crash)。迭代器失效就是指:迭代器内部的指针没有及时更新,依然指向旧内存空间的元素。

怎么解析C++ 的STL迭代器原理和实现

上图展示了STL源码中vector容器insert方法的实现方式。当插入的元素个数超过当前容器的剩余容量时,就会导致迭代器失效。这也是测试代码中myvector.insert (it,200,300);插入200个元素的原因,为了模拟超过当前容器剩余容量的场景,如果你的测试环境没有crash,可以将插入元素设置的更多一些。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网其他教程频道,感谢您对编程网的支持。

--结束END--

本文标题: 怎么解析C++ 的STL迭代器原理和实现

本文链接: https://www.lsjlt.com/news/307162.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么解析C++ 的STL迭代器原理和实现
    怎么解析C++ 的STL迭代器原理和实现,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1. 迭代器简介为了提高C++编程的效率,STL(Standar...
    99+
    2023-06-26
  • 详解C++ 的STL迭代器原理和实现
    1. 迭代器简介 为了提高C++编程的效率,STL(Standard Template Library)中提供了许多容器,包括vector、list、map、set等。然而有些容器(...
    99+
    2022-11-12
  • java迭代器实现的原理是什么
    Java迭代器的实现原理是基于设计模式中的迭代器模式。迭代器模式是一种行为型模式,它提供了一种方法来顺序访问一个聚合对象中的元素,而...
    99+
    2023-10-10
    java
  • 一文带你解密Python迭代器的实现原理
    目录可迭代对象与迭代器迭代器的创建迭代器的底层结构元素迭代的具体过程小结可迭代对象与迭代器 Python 一切皆对象,类型对象定义了哪些操作,决定了实例对象拥有哪些行为。 比如类型对...
    99+
    2022-12-14
    Python迭代器原理 Python迭代器
  • c语言解释器的实现原理是什么
    C语言解释器的实现原理是将C语言源代码转换为可执行的机器代码并执行。下面是C语言解释器的基本实现原理:1. 词法分析:将源代码分解为...
    99+
    2023-08-08
    c语言
  • golang定时器Timer的用法和实现原理解析
    目录一文搞懂golang定时器Timer的用法和实现原理前言Timertimer结构体创建定时器停止定时器重置定时器实现原理数据结构runtimeTimer创建Timer停止Time...
    99+
    2023-05-15
    golang定时器 golang定时器Ticker
  • 怎么用C++实现简易的.ini配置文件解析器
    本篇内容介绍了“怎么用C++实现简易的.ini配置文件解析器”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在最开始实例化一个IniHelpe...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作