【C++】C++ STL 探索:List使用与背后底层逻辑(三)

简介: 【C++】C++ STL 探索:List使用与背后底层逻辑

【C++】C++ STL 探索:List使用与背后底层逻辑(二)https://developer.aliyun.com/article/1617349


List.h

#include <iostream>
using namespace std;
//链表 任意位置插入 不怕迭代器失效
//链表 任意位置删除 怕迭代器失效 对此需要传下一个位置的迭代器
namespace bit
{
  //节点
  template<class T>
  struct ListNode
  {
    ListNode<T>* _next;
    ListNode<T>* _prev;
    T _data;
    //创建节点,是传数据创建的
    ListNode(const T& x = T())
      :_next(nullptr)
      ,_prev(nullptr)
      ,_data(x)
    {}
  };
  //template<class T>
  //
  template<class T,class Ref, class Ptr>
  struct ListIterator
  {
    typedef ListNode<T> Node;
    typedef  ListIterator<T,Ref,Ptr> Self;
    Node* _node;
    
    //迭代器还是依赖指针,通过类来改变运算符的行为
    //这里是浅拷贝 拷贝构造函数
    ListIterator(Node* node)
      :_node(node)
    {}
    //Self& operator++()
    Self& operator++()
    {
      _node = _node->_next;
      return *this;
    }
    //后缀++
    Self operator++(int)
    {
      //构造一个tmp临时变量
      Self tmp(*this);
      _node = _node->_next;
      return tmp;
    }
    Self& operator--()
    {
      _node = _node->_prev;
      return *this;
    }
    //后缀--
    Self operator--(int)
    {
      //构造一个tmp临时变量
      Self tmp(*this);
      _node = _node->_prev;
      return tmp;
    }
    // T& operator* ()
      Ref operator* ()
    {
      return _node->_data;
    }
     //通过指针指向的节点去判断是否相等
     bool operator==(const Self& it)
     {
       return _node == it._node;
    }
     bool operator!=(const Self& it)
     {
       return _node != it._node;
     }
     //T* operator->()
    Ptr operator->()
     {
       return &_head->_data;
     }
  };
  //template<class T>
  //struct ListConIterator
  //{
  //  typedef ListNode<T> Node;
  //  typedef  ListConIterator<T> Self;
  //  //只针对解引用 修改了迭代器的行为 但是++ --是将迭代器位置改变,迭代器指向的内容不能被修改
  //  Node* _node;
  //  //迭代器还是依赖指针,通过类来改变运算符的行为
  //  //这里是浅拷贝 拷贝构造函数
  //  ListIterator(Node* node)
  //    :_node(node)
  //  {}
  //  Self& operator++()
  //  {
  //    _node = _node->_next;
  //    return *this;
  //  }
  //  //后缀++
  //  Self operator++(int)
  //  {
  //    //构造一个tmp临时变量
  //    Self tmp(*this);
  //    _node = _node->_next;
  //    return tmp;
  //  }
  //  //这里需要判断空
  //  Self& operator--()
  //  {
  //    _node = _node->_prev;
  //    return *this;
  //  }
  //  //
  //  
  //  //后缀--
  //   Self operator--(int) 
  //  {
  //    //构造一个tmp临时变量
  //    Self tmp(*this);
  //    _node = _node->_prev;
  //    return tmp;
  //  }
  //   
  //   T& operator* () 
  //  {
  //    return _node->_data;
  //  }
  //  //通过指针指向的节点去判断是否相等
  //  bool operator==(const Self& it)
  //  {
  //    return _node == it._node;
  //  }
  //  bool operator!=(const Self& it)
  //  {
  //    return _node != it._node;
  //  }
  //   T* operator->() 
  //  {
  //    return &_head->_data;
  //  }
  //};
  template<class T>
  class list
  {
    typedef ListNode<T> Node;
    public:
      //typedef  ListIterator<T> Iterator;
      typedef ListIterator<T, T&, T*> Iterator;
      typedef ListIterator<T, const T&, const T*> const_Iterator;
      //不要传引用,不要修改这些位置
      Iterator begin()
      {
        //return Iterator(_head->_next);
        //单参数的拷贝构造函数支持隐式类型转换
        return _head->_next;
      }
      Iterator end()
      {
        //return Iterator(_head);
        return _head;
      }
      const Iterator begin() const
      {
        return _head->_next;
      }
      const Iterator end() const
      {
        return _head;
      }
      const_Iterator begin() const
      {
        //return Iterator(_head->_next);
        //单参数的拷贝构造函数支持隐式类型转换
        return _head->_next;
      }
      const_Iterator end() const
      {
        //return Iterator(_head);
        return _head;
      }
      //构造-->同时拷贝需要也需要一份节点 那么就可以复用同一份
      void empty_init()
      {
        _head = new Node;
        _head->_next = _head;
        _head->_prev = _head;
        //不需要 newndoe->date 在实例化时,data已经是0了
        _size = 0;
      }
      
      list()
      {
        empty_init();
      }
      
      //拷贝构造
       list(const list<T>& lt)
      {
        empty_init();
        for (auto e : lt)
        {
          push_back(e);
        }
      }
      
       list<T>& operator=(list<T>& it)
       {
         swap(it);       
         return *this;
       }
       void swap(list<T>& it)
       {
         std::swap(_head, it._head);
         std::swap(_size, it._size);
       }
       //通过迭代器来实现
      void  insert(Iterator pos, const T& val)
       {
         Node* newnode = new Node(val);
         Node* cur = pos._node;
         Node* prev = cur->_prev;
         
         newnode->_next = cur;
         newnode-> _prev = prev;
         cur->_prev = newnode;
         prev->_next = newnode;
         _size++;
       }
      //这些需要使用迭代器作为返回类型,怕出现迭代器失效
      Iterator& erase(Iterator pos)
       {
        Node* cur = pos._node;
        Node* next = cur->_next;
        Node* prev = cur->_prev;
        delete cur;
        next->_prev = prev;
        prev->_next = next;
        
        _size--;
        //注意点
        return Iterator(next);
       }
      
      void push_back(const T& val)
      {
        insert(end(), val);
      }
      void pop_back()
      {
        erase(--end());
      }
      void push_front(const T& val)
      {
        insert(begin(), val);
      }
      void pop_front()
      {
        erase(begin());
      }
      void clear()
      {
        Iterator it = begin();
        while (it != end())
        {
          it = erase(it);
        }
      }
      ~list()
      {
        clear();        
        delete _head;
        _head = nullptr;
      }
       //获得基本信息
       size_t size()
       {
         return _size;
       }
       bool empty()
       {
         return _size == 0;
       }
    private:
      //创建哨兵位
      Node* _head;
      size_t _size;
  };
  struct A
  {
    int a1 = 0, a2 = 0;
    
    A(int a1 , int a2)
      :a1(1)
      ,a2(2)
    {}
  };
  void PrintList(const list<int>& clt)
  {
    list<int> ::Iterator it = clt.begin();
    while (it != clt.end())
    {
      *it += 10;
      cout << *it << " ";
      ++it;
    }
    cout << endl;
  }
  void list_test()
  {
    //list<int> it;
    先插入
    //it.push_back(1);
    //it.push_back(2);
    //list<int> :: Iterator lt = it.begin();
    
    //A* ptr = &a1
    // (*ptr).a1;
    // ptr->_a1
    //返回的是临时变量 是一份临时拷贝 具有常性
    list<A> lt;
    list<A> ::Iterator it = lt.begin();
    lt.push_back(A(1,2));
    lt.push_back({3,3});
    while (it != lt.end())
    {
      cout << *it;
      it++;
    }
  }
}


以上就是本篇文章的所有内容,在此感谢大家的观看!这里是店小二呀C++笔记,希望对你在学习C++语言旅途中有所帮助!

目录
打赏
0
2
2
0
21
分享
相关文章
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
32 2
|
16天前
|
【c++丨STL】map/multimap的使用
本文详细介绍了STL关联式容器中的`map`和`multimap`的使用方法。`map`基于红黑树实现,内部元素按键自动升序排列,存储键值对,支持通过键访问或修改值;而`multimap`允许存在重复键。文章从构造函数、迭代器、容量接口、元素访问接口、增删操作到其他操作接口全面解析了`map`的功能,并通过实例演示了如何用`map`统计字符串数组中各元素的出现次数。最后对比了`map`与`set`的区别,强调了`map`在处理键值关系时的优势。
121 73
|
18天前
|
【c++丨STL】set/multiset的使用
本文深入解析了STL中的`set`和`multiset`容器,二者均为关联式容器,底层基于红黑树实现。`set`支持唯一性元素存储并自动排序,适用于高效查找场景;`multiset`允许重复元素。两者均具备O(logN)的插入、删除与查找复杂度。文章详细介绍了构造函数、迭代器、容量接口、增删操作(如`insert`、`erase`)、查找统计(如`find`、`count`)及`multiset`特有的区间操作(如`lower_bound`、`upper_bound`、`equal_range`)。最后预告了`map`容器的学习,其作为键值对存储的关联式容器,同样基于红黑树,具有高效操作特性。
44 3
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
【c++丨STL】priority_queue(优先级队列)的使用与模拟实现
本文介绍了STL中的容器适配器`priority_queue`(优先级队列)。`priority_queue`根据严格的弱排序标准设计,确保其第一个元素始终是最大元素。它底层使用堆结构实现,支持大堆和小堆,默认为大堆。常用操作包括构造函数、`empty`、`size`、`top`、`push`、`pop`和`swap`等。我们还模拟实现了`priority_queue`,通过仿函数控制堆的类型,并调用封装容器的接口实现功能。最后,感谢大家的支持与关注。
79 1
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
41 16
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。
|
25天前
|
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
70 6
目录
目录
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等