C/C++编程:使用模板实现一个链式容器的迭代器

亦凉 2023-01-17 02:23 115阅读 0赞
  1. #include <stdexcept>
  2. template<typename T> class list; // 前置声明,用于声明友元类
  3. template<typename N>
  4. class list_iterator{
  5. N * pos;
  6. template<typename T> friend class list; //list模板可访问私有成员以进行插入等操作
  7. public:
  8. // 重命名各种类型以方便其他模板提取
  9. typedef typename N::value_type value_type; // 标记迭代器所指数据的类型
  10. typedef typename N::reference_type reference_type; // 标记迭代器所指数据的引用
  11. typedef typename N::const_reference_type const_reference_type; // 标记迭代器所指数据的只读引用类型
  12. typedef list_iterator<N> self_type;
  13. list_iterator() : pos(0) {
  14. } // 构造一个空迭代器
  15. list_iterator(N *pos) : pos(pos) {
  16. }
  17. bool operator!= (self_type const &right) const {
  18. return pos != right.pos;
  19. }
  20. bool operator== (self_type const &right) const {
  21. return pos == right.pos;
  22. }
  23. self_type & operator++ (){
  24. if(pos){
  25. pos = pos->next;
  26. }
  27. return *this;
  28. }
  29. reference_type operator* () noexcept (false){
  30. if (pos){
  31. return pos->value;
  32. }else{
  33. throw std::runtime_error("dereferencing null iterator!");
  34. }
  35. }
  36. };

通过typedef按约定好的规则预定义一些类型以描述本模板的相关特性时常见且非常重要的一种手段。这一段代码是基于在节点类N中有同样的类型名定义的假定。有此定义后,就可以通过比如下面代码提取出迭代器所指元素类型并加以应用等:

  1. list_iterator<linked_list_node>::value_type a;

另外,这三行typedef语句中还在嵌套标识符N::value_type、N::reference_type以及N::const_reference_type之前必须用typename修饰。因为N是一个模板参数,编译器仅知道其为一个类型,对于嵌套其内的标识符,编译器无从判断其意义。N::value_type 也可能是类型N的一个静态成员变量名、成员函数名、嵌套定义的枚举值名。在无从推断嵌套标识符的意义时,编译器首先假定该标识符不是类型名,在根据上下文判断。所以,当嵌套标识符确为类型名时,须在其前加typename修饰以免编译器报错。

  1. // 链表节点类模板
  2. template<typename T>
  3. struct list_node{
  4. typedef T value_type;
  5. typedef T& reference_type;
  6. typedef const T& const_reference_type;
  7. T value;
  8. list_node *prev;
  9. list_node *next;
  10. list_node(T const &value, list_node *prev, list_node *next) :
  11. value(value), prev(prev), next(next){
  12. }
  13. };
  14. // 链表类模板
  15. template<typename T>
  16. class list{
  17. typedef list_node<T> node_type;
  18. node_type *head; // 头节点指针
  19. public:
  20. // 类型定义
  21. typedef T value_type;
  22. typedef list_iterator<node_type> iterator;
  23. list() :head() {
  24. }
  25. ~list(){
  26. // 析构时删除链表节点空间
  27. while (head){
  28. node_type *n = head;
  29. head = head->next;
  30. delete n;
  31. }
  32. }
  33. // 从表头插入数据
  34. void push_front(T const &v){
  35. head = new node_type (v, 0, head);
  36. if(head->next){
  37. head->next->prev = head;
  38. }
  39. }
  40. // 从表头删除数据
  41. void pop_front(T const &v){
  42. if(head){
  43. node_type *n = head;
  44. head = head->next;
  45. head->prev = 0;
  46. delete n;
  47. }
  48. }
  49. // 指定位置后面插入元素
  50. void insert(iterator it, T const &v){
  51. node_type *n = it.pos;
  52. if(n){
  53. node_type *new_node = new node_type (v, n, n->next);
  54. new_node->next->prev = new_node;
  55. n->next = new_node;
  56. }
  57. }
  58. // 删除指定元素
  59. void erase(iterator *it){
  60. node_type *n = it->pos;
  61. ++it; // 将迭代器指向下一个元素
  62. if(n){
  63. if(n->next){
  64. n->next->prev = n->prev;
  65. }
  66. if(n->prev){
  67. n->prev->next = n->next;
  68. }
  69. if(head == n){
  70. head = n->next;
  71. }
  72. delete n;
  73. }
  74. }
  75. bool is_empty() const {
  76. return head == 0;
  77. }
  78. iterator begin(){
  79. return iterator (head);
  80. }
  81. iterator end(){
  82. return iterator ();
  83. }
  84. };

发表评论

表情:
评论列表 (有 0 条评论,115人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++容器/

    C++容器 简介 vector用来代替数组(动态数组),顺序存储 list是链表,多用表经常使用插入删除的地方,每个对象都有前向指针和后象指针,在内存里也不一定是

    相关 【STL容器学习】-

    STL中的容器类广泛使用迭代器,迭代器是一种对象,使用它可方便地对容器中的元素进行遍历。迭代器与内置指针很相似,都提供了一种访问和操纵容器中元素的方便途径。迭代器可以分为以下5

    相关 C++容器

    一、顺序容器vector 1.1 容器是什么        在C++中,容器被定义为:在数据存储上,有一种对象类型,它可以持有其他对象或指向其他对象的指针,这种对象