简易实现 STL--list

简介: 简易实现 STL--list

实现 list 的主要思想及过程

首先,实现过程中的所有代码必须放在自己定义的命名空间中。

定义一个结点的结构体类模板,结点的数据类型就应该是模板类型 T,定义的 next指针和 prev指针都应该是模板指针类型,并且结构体类中药有构造函数,确保在 new 结点的时候,不会出现未初始化的情况。

第二步就是定义一个迭代器的类模板,其中模板参数要有三个,分别做数据类型和返回值类型,保证普通迭代器和 const 类型的迭代器都能通用,在泛型编程下,只要保证模板参数的数量足够,编译器就能自动推导需要的数据类型!

最后一步就是写出 list 的类模板,这个其实只需要传一个模板参数即可,在使用迭代器的时候,使用迭代器自己实例化的模板参数来自动推导即可。

因为list 在使用迭代器的时候只需要控制普通迭代器和 const 迭代器的返回类型即可,所以只需要两种不同模板参数的迭代器区分返回值即可。

#include<iostream>
using namespace std;
namespace zyb
{
  template<class T>
  struct list_node
  {
    T _val;
    list_node<T>* _next;
    list_node<T>* _prev;
    list_node(const T& x = T())
      :_val(x),
      _next(nullptr),
      _prev(nullptr)
    {}
  };
  template<class T,class Ref,class Ptr>
  struct __list_iterator
  {
    typedef list_node<T> Node;
    typedef __list_iterator<T, Ref, Ptr> self;
    Node* _node;
    __list_iterator(Node* node)
      :_node(node)
    {
    }
    self operator++(int)
    {
      self tmp = __list_iterator(_node);
      _node = _node->_next;
      return tmp;
    }
    self operator--(int)
    {
      self tmp = __list_iterator(_node);
      _node = _node->_prev;
      return tmp;
    }
    self& operator++()
    {
      _node = _node->_next;
      return *this;
    }
    self& operator--()
    {
      _node = _node->_prev;
      return *this;
    }
    bool operator==(const self& it)
    {
      return it._node == _node;
    }
    bool operator!=(const self& it)
    {
      return it._node != _node;
    }
    Ref operator*()
    {
      return _node->_val;
    }
    Ptr operator->()
    {
      return &(_node->_val);
    }
  }; 
}

泛型编程中模板的再理解

过程中学习到的一些模板的知识:如何自己实现一个函数,可以打印不同容器中不同的数据类型?

这是实现 list 的不同数据打印的代码,值得注意的是,在 list<T> 前面加了一个 typename  ,包括前面的模板声明,也用的是 typename 这是为什么呢?

如果不加 typename ,因为 list<T>  就是未实例化的模板,因为类型是不确定的,里面会有好多未确认的类型,并且编译器无法辨别 const_iterator 是 内嵌类型 还是 静态成员变量(只有内嵌类型和静态成员变量才能通过类域去访问),编译器就会报错那么前面加一个 typename,就相当于一个给编译器的声明,这是一个内嵌类型(保证编译的时候不会报错),等 list<T> 实例化之后,再去对应的类里找到实例化类型来替换。

template<typename T>
  void print_list(const list<T>& lt)
  {
    typename list<T>::const_iterator it1 = lt.begin();
    while (it1 != lt.end())
    {
      cout << *it1 << ' ';
      ++it1;
    }
    cout << endl;
    for (auto e : lt)
    {
      cout << e << ' ';
    }
  }

当然,也可以改写为一个针对全部容器打印数据的代码,

Container 的类型根据传入的容器类型来推导出来,相当于对于上面的模板再抽象了一层。

这就是泛型编程!

template<typename Container>
  void print_container(const Container& x)
  {
    typename Container::const_iterator it1 = x.begin();
    while (it1 != x.end())
    {
      cout << *it1 << ' ';
      ++it1;
    }
    cout << endl;
    for (auto e : x)
    {
      cout << e << ' ';
    }
  }
相关文章
如何用限制立方样条(RCS)做生存分析?
如何用限制立方样条(RCS)做生存分析?
1683 0
如何用限制立方样条(RCS)做生存分析?
|
9月前
|
人工智能 算法 小程序
AI试衣技术:为什么能生成好看的图片,却难以真正用于商业场景?
本文解析AI试衣技术背后的真实挑战,指出娱乐化“AI换衣”与商业级虚拟试衣的本质差异,揭示体型适配、服装结构还原等核心难题,并探讨行业领先者如何通过多维度技术积累实现可商用的精准、真实、稳定的虚拟试穿方案。
1097 6
|
存储 人工智能 运维
超大规模云数据中心对存储的诉求有哪些?
要实现超大规模部署的特性,就对存储有别于普通数据中心或者消费市场的诉求。具体有哪些呢?主要有以下几点,我们针对部分信息展开讨论
|
Kubernetes 负载均衡 算法
k8s学习--kube-proxy的三种工作模式详细解释
k8s学习--kube-proxy的三种工作模式详细解释
1004 0
|
Web App开发
折腾Chrome 插件,怎么给右键菜单增加“选项”?
折腾Chrome 插件,怎么给右键菜单增加“选项”?
623 0
|
存储 Ubuntu Shell
Ubuntu 使用deepin-wine源移植
1、详细看 https://github.com/zq1997/deepin-wine 2、添加仓库 首次使用时,你需要运行如下一条命令将移植仓库添加到系统中。 wget -O- https://deepin-wine.i-m.dev/setup.sh | sh 3、应用安装 自此以后,你可以像对待普通的软件包一样,使用apt-get系列命令进行各种应用安装、更新和卸载清理了。 比如安装微信只需要运行下面的命令。 sudo apt-get install com.qq.weixin.deepin 将com.qq.weixin.deepin替换为下列包名,可以继续安装其他应用:
921 1
|
机器学习/深度学习 人工智能 算法
基于Python进行人脸验证人脸识别系统 毕业设计附完整代码 可直接运行
基于Python进行人脸验证人脸识别系统 毕业设计附完整代码 可直接运行
1151 0
基于Python进行人脸验证人脸识别系统 毕业设计附完整代码 可直接运行
|
人工智能 前端开发 数据可视化
如何做好一份程序员的工作汇报ppt?
如何做好一份程序员的工作汇报ppt?
如何做好一份程序员的工作汇报ppt?
|
传感器 机器人 监控
带你读《传感器系统:基础及应用》之一:工程中的传感器系统
本书包括传感器相关的数学、物理、电路等基础理论,介绍了相关的性能指标、性能选择以及集成到工程系统所需的软硬件,讲述了先进的传感器技术、分析建模、实际应用和设计研究实例。全书共12章,前面7章是传感器的基础知识,第8~11章分别讨论了不同种类传感器的结构及实际应用,第12章涉及先进的传感器技术。 本书可以作为高等学校测控技术与仪器、自动化、机电一体化、电气工程等专业高年级本科生和研究生教材,也可供相关科研和工程技术人员学习参考。