STL容器之list类

文章目录

  • STL容器之list类
    • 1、list的介绍
    • 2、list的使用
      • 2.1、list的常见构造
      • 2.2、list的iterator的使用
      • 2.3、list空间增长问题
      • 2.4、list的增删查改
      • 2.5、list迭代器失效问题
    • 3、list的模拟实现(含反向迭代器)

img

STL容器之list类

1、list的介绍

  • list是序列容器,允许在序列中的任何地方进行常数时间插入和删除操作,以及双向迭代。

  • list容器是由双向链表实现;双向链表可以将它们包含的每个元素存储在不同和不相关的存储位置。在节点中通过指针指向其前一个元素和后一个元素。

  • list与forward_list非常相似:主要区别在于forward_list对象是单链表,只能朝前迭代,以让其更简单高效。

  • 与其他基本标准序列容器(array、vector和deque)相比,list可以在任何位置插入、提取和移动元素方面通常表现更好,因此在密集使用这些元素的算法(如排序算法)中也表现更好。

  • 与这些其他序列容器相比,list和forward_lists的主要缺点是它们无法通过位置直接访问元素;例如,要访问列表中的第六个元素,必须从已知位置(如开始或结束)到该位置,这在它们之间的距离上需要线性时间。它们还消耗一些额外的内存来保存与每个元素相关的链接信息(这可能是大型小元素列表的一个重要因素)。

  • list底层是带头双向循环链表。


2、list的使用

2.1、list的常见构造

(constructor )函数名称接口说明
list (size_type n, const value_type& val = value_type())构造一个长度为n的list,每个元素的值为val
list()构造空的list
list (InputIterator first, InputIterator last)用迭代区间[first,last)构造list
list (const list& x)拷贝构造list
#include <iostream>

#include <list>

using namespace std;

void test_list4(){
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.push_back(6);

    for (auto e: lt) {
        cout << e << " ";
    }
    cout << endl;

    list<int> lt1(10,2);
    for (auto e: lt1) {
        cout << e << " ";
    }
    cout << endl;

    list<int> lt2(lt1.begin(),lt1.end());
    for (auto e: lt2) {
        cout << e << " ";
    }
    cout << endl;

    list<int> lt3(lt2);
    for (auto e: lt3) {
        cout << e << " ";
    }
    cout << endl;
    
}

int main() {
  
    test_list4();
    return 0;
  
}

2.2、list的iterator的使用

函数名称接口说明
begin()+end()获取第一个元素位置的iterator/const_iterator和获取最后一个元素的后一个位置的iterator/const_iterator
rbegin()+rend()获取最后一个元素位置的reverse_iterator/const_reverse_iterator和获取第一个元素的后一个位置的reverse_iterator/const_reverse_iterator
#include <iostream>

#include <list>

using namespace std;

void test_list5(){
 list<int> lt;
 lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.push_back(6);
   
    list<int>::iterator it = lt.begin();
 while(it != lt.end()){
        cout << *it << " ";
        ++it;
    }
    cout <<endl;
   
   
 list<int>::reverse_iterator rit = lt.rbegin();
 while(rit != lt.rend()){
        cout << *rit << " ";
        ++rit;
    }
    cout <<endl;
   }
   
int main() {

 test_list5();
   return 0;
   
   }

2.3、list空间增长问题

函数名称接口说明
empty判断list是否为空
size返回list长度/结点个数
#include <iostream>

#include <list>

using namespace std;

void test_list6() {
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.push_back(6);

    cout << lt.size() << endl;
    cout << lt.empty() << endl;

    lt.assign(0,0);
    cout << lt.size() << endl;
    cout << lt.empty() << endl;
}

int main() {

 test_list6();
 return 0;

}

2.4、list的增删查改

函数名称接口说明
front
back
push_front
pop_front
push_back
pop_back
insert
erase
swap
clear
#include <iostream>

#include <list>

using namespace std;

void test_list7() {
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);
    lt.push_back(6);

    for (auto e: lt) {
        cout << e << " ";
    }
    cout << endl;

    cout << lt.front() << endl;
    cout << lt.back() << endl;

    lt.push_front(10);
    lt.push_back(9);
    for (auto e: lt) {
        cout << e << " ";
    }
    cout << endl;

    lt.pop_front();
    lt.pop_back();
    for (auto e: lt) {
        cout << e << " ";
    }
    cout << endl;

    lt.insert(find(lt.begin(),lt.end(),4),40);
    for (auto e: lt) {
        cout << e << " ";
    }
    cout << endl;

    list<int>::iterator it = lt.erase(find(lt.begin(),lt.end(),6));
    for (auto e: lt) {
        cout << e << " ";
    }
    cout << endl;

    list<int> lt1(10,1);
    swap(lt,lt1);
    for (auto e: lt) {
        cout << e << " ";
    }
    cout << endl;

    for (auto e: lt1) {
        cout << e << " ";
    }
    cout << endl;

    lt.clear();
    for (auto e: lt) {
        cout << e << " ";
    }
    cout << endl;

}

int main() {

 test_list7();
 return 0;

}

2.5、list迭代器失效问题

  • list迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际是对指针进行了封装

  • 迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。

  • 因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响

    void TestListIterator1()
    {
        int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
        list<int> l(array, array+sizeof(array)/sizeof(array[0]));
        auto it = l.begin();
        while (it != l.end())
        {
            // erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给其赋值
    //        l.erase(it);
            it = l.erase(it);
            ++it;// 每次跳一个删除
        }
    }
    

3、list的模拟实现(含反向迭代器)

注意:list的模拟实现用到了比较多的模版,同时还用到了组合(其中之一就是反向迭代器的实现),相对于string和vector的模拟实现会更难。

  • vector.h文件

    //
    // Created by 徐鹏 on 2023/12/10.
    //
      
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <list>
      
    #include "ReverseIterator.h"
      
    using namespace std;
      
    #ifndef DEMO_01_VECTOR_H
    #define DEMO_01_VECTOR_H
      
    #endif //DEMO_01_VECTOR_H
      
    namespace xp {
        template<typename T>
        class vector {
        public:
            typedef T *iterator;
            typedef const T *const_iterator;
      
            typedef ReverseIterator<iterator, T &, T *> reverse_iterator;
            typedef ReverseIterator<const_iterator, const T &, const T *> const_reverse_iterator;
    
    
            vector() : _start(nullptr), _finish(nullptr), _end_of_storage(nullptr) {}
    
    //        vector(const vector<T> &v) {
    //            _start = new T[v.capacity()];
    //            memcpy(_start, v._start, v.size() * sizeof(T));
    //            _finish = _start + v.size();
    //            _end_of_storage = _start + capacity();
    //        }
    
            //拷贝构造函数
            vector(const vector<T> &v) {
                reserve(v.capacity());
                for (const auto &e: v) {
                    push_back(e);
                }
            }
        
            template<class InputIterator>
            //构造迭代器区间
            vector(InputIterator first, InputIterator last) {
                while (first != last) {
                    push_back(*first);
                    ++first;
                }
            }
        
            vector(size_t n, const T &val = T()) {
                resize(n, val);
            }
        
            //防止和上面迭代器区间搞混
            vector(int n, const T &val = T()) {
                resize(n, val);
            }
        
            //赋值 ,这里vector<T> v在传值的时候就已经有拷贝构造了
            vector<T> &operator=(vector<T> v) {
                swap(v);
                return *this;
            }
        
            T &operator[](size_t n) {
                return *(_start + n);
            }
        
            const T &operator[](size_t n) const {
                return *(_start + n);
            }
        
            ~vector() {
                if (_start) {
                    delete[] _start;
                    _start = _finish = _end_of_storage = nullptr;
                }
            }
        
            void swap(vector<T> v) {
                std::swap(_start, v._start);
                std::swap(_finish, v._finish);
                std::swap(_end_of_storage, v._end_of_storage);
            }
        
            void reserve(size_t n) {
                if (n > capacity()) {
                    //开辟新空间
                    size_t old_size = size();
                    iterator tmp = new T[n];
                    //start不为空,在复制完内容需要释放空间
                    if (_start) {
    //                    //对于自定义类型,在进行delete[] _start 之后(自定义类型里面存在指针开辟空间问题的时候),会把原来的_start里面内容进行析构和空间释放
    //                    memcpy(tmp, _start, old_size * sizeof(T));
    
                        //  解决方案,进行深拷贝
                        for (size_t i = 0; i < old_size; ++i) {
                            tmp[i] = _start[i];
                        }
                        delete[] _start;
                    }
                    _start = tmp;
                    //这里要注意,得用之前的size,不然新size使用内联进来就是_finish = _start + _finish - _start
                    _finish = _start + old_size;
                    _end_of_storage = _start + n;
                }
            }
        
            void resize(size_t n, T val = T()) {
                if (n > capacity()) {
                    size_t fill = _start + n - _finish;
                    reserve(n);
                    //填补之前finish后面fill个数据
                    while (fill != 0) {
                        *_finish = val;
                        _finish++;
                        fill--;
                    }
                }
            }
        
            void push_back(const T &val) {
                if (_finish == _end_of_storage) {
                    size_t newCapacity = capacity() == 0 ? 4 : 2 * capacity();
                    reserve(newCapacity);
                }
                *_finish = val;
                ++_finish;
            }
        
            void pop_back() {
                --_finish;
            }
        
            void insert(iterator pos, const T &val) {
                assert(pos >= _start);
                assert(pos <= _finish);
        
                if (_finish == _end_of_storage) {
                    size_t len = pos - _start;
                    size_t newCapacity = capacity() == 0 ? 4 : 2 * capacity();
                    reserve(newCapacity);
                    pos = _start + len;//防止增容量后,pos位置还是之前被释放的空间
                }
                //memmove(pos + 1, pos, sizeof(T) * (_finish - pos)); //浅拷贝,扩容可能存在迭代器失效问题
                iterator end = _finish - 1;
                while (pos <= end) {
                    *(end + 1) = *end;
                    --end;
                }
                *pos = val;
                ++_finish;
            }
        
            iterator begin() {
                return _start;
            }
        
            const_iterator begin() const {
                return _start;
            }
        
            iterator end() {
                return _finish;
            }
        
            const_iterator end() const {
                return _finish;
            }
        
            reverse_iterator rbegin() {
                return end();
            }
        
            const_reverse_iterator rbegin() const {
                return end();
            }
        
            reverse_iterator rend() {
                return begin();
            }
        
            const_reverse_iterator rend() const{
                return begin();
            }
    
    
            size_t size() const {
                return _finish - _start;
            }
        
            size_t capacity() const {
                return _end_of_storage - _start;
            }
        
        private:
            iterator _start = nullptr;
            iterator _finish = nullptr;
            iterator _end_of_storage = nullptr;
        };
        
        void test_vector1() {
            vector<char> v;
            v.reserve(10);
            cout << v.size() << " " << v.capacity() << endl;
    //        v.resize(100);
            v.resize(100, 'x');
            cout << v.size() << " " << v.capacity() << endl;
    
        }
        
        void test_vector2() {
            vector<int> v;
            v.push_back(1);
            v.push_back(2);
            v.push_back(3);
            v.push_back(4);
            v.push_back(5);
            for (auto e: v) {
                cout << e << " ";
            }
            cout << endl;
        }
        
        void test_vector3() {
            vector<string> v;
            v.push_back("hh");
            v.insert(v.begin(), "2");
            v.insert(v.begin(), "2");
            v.insert(v.begin(), "2");
            v.insert(v.begin(), "2");
            v.insert(v.begin(), "2");
            v.insert(v.begin(), "2");
            v.insert(v.begin(), "2");
            v.insert(v.begin(), "2");
            for (auto e: v) {
                cout << e << " ";
            }
            cout << endl;
        }
        
        void test_vector4() {
            vector<string> v1;
            v1.push_back("hhh");
            v1.push_back("www");
            for (auto e: v1) {
                cout << e << " ";
            }
            cout << endl;
        
            vector<string> v2;
            v2.push_back("lllll");
            v2.push_back("nnnnn");
            for (auto e: v2) {
                cout << e << " ";
            }
            cout << endl;
            cout << "----------------------" << endl;
            v1 = v2;
            for (auto e: v1) {
                cout << e << " ";
            }
            cout << endl;
            for (auto e: v2) {
                cout << e << " ";
            }
            cout << endl;
        
        }
        
        void test_vector5() {
            vector<string> v;
            v.push_back("w");
            v.push_back("s");
            v.push_back("x");
            v.push_back("p");
            cout << v[1] << endl;
        }
        
        void test_vector6() {
            vector<string> v;
            v.push_back("w");
            v.push_back("s");
            v.push_back("x");
            v.push_back("p");
            v.push_back("p");
            v.push_back("p");
            v.push_back("p");
            v.push_back("p");
            v.push_back("psdf");
            v.push_back("pdsf");
            v.push_back("pfd");
            v.push_back("pdsf");
            v.insert(v.begin(), "sdas");
            for (auto e: v) {
                cout << e << " ";
            }
            cout << endl;
        }
        
        void test_vector7() {
            vector<string> v;
            v.push_back("w");
            v.push_back("s");
            v.push_back("x");
            v.push_back("p");
            v.push_back("p");
            v.push_back("p");
            vector<string> v2(v.begin(), v.end());
            for (auto e: v2) {
                cout << e << " ";
            }
            cout << endl;
        
            int a[] = {1111, 222, 222, 3};
            vector<int> v3(a, a + 4);
            for (auto e: v3) {
                cout << e << " ";
            }
            cout << endl;
        
            list<string> lt;
            lt.push_back("hjakds");
            lt.push_back("wq");
            lt.push_back("qw");
            lt.push_back("w");
        
            vector<string> v4(lt.begin(), lt.end());
            for (auto e: v4) {
                cout << e << " ";
            }
            cout << endl;
        
            vector<int> v5(5, 5);
            for (auto e: v5) {
                cout << e << " ";
            }
            cout << endl;
        }
        
        void test_vector8() {
            vector<int> v;
            v.push_back(1);
            v.push_back(2);
            v.push_back(3);
            v.push_back(4);
            v.push_back(5);
        
            vector<int>::reverse_iterator rit = v.rbegin();
            while (rit != v.rend()) {
                cout << *rit << " ";
                rit++;
            }
            cout << endl;
        }
    
    }
    
  • list.h文件

    //
    // Created by 徐鹏 on 2024/3/3.
    //
    
    #ifndef DEMO_05_LIST_H
    #define DEMO_05_LIST_H
    
    #endif //DEMO_05_LIST_H
    
    #include "ReverseIterator.h"
    #include <iostream>
    
    using namespace std;
    
    
    // list的模拟实现(还未完成)
    
    namespace xp {
    
        // 结点
        template<class T>
        struct ListNode {
            ListNode<T> *_next;
            ListNode<T> *_prev;
            T data;
    
            // 构造函数  -- 创建结点
            ListNode(const T val = T()) : _next(nullptr), _prev(nullptr), data(val) {
    
            }
        };
    
        template<class T, class Ref, class Ptr>
        class __list_iterator {
        public:
            typedef ListNode<T> Node;
            typedef __list_iterator<T, Ref, Ptr> self; // 迭代器本身
    
            // 这里构造函数为了方便begin和end,直接隐式类型转换
            __list_iterator(Node *node) : _node(node) {
    
            }
    
            Ref operator*() {
                return _node->data;
            }
    
            Ptr operator->() {
                return &_node->data;
            }
    
            self &operator++() {
                _node = _node->_next;
                return *this;
            }
    
            self operator++(int) {
                self temp(*this); // 这里*this的类型是self ,调用默认拷贝构造函数!因为是内置类型,不需要自己写
                _node = _node->_next;
                return temp;
            }
    
            self &operator--() {
                _node = _node->_prev;
                return *this;
            }
    
            self &operator--(int) {
                self temp(*this);
                _node = _node->_prev;
                return temp;
            }
    
            bool operator!=(const self &s) {
                return _node != s._node;
            }
    
            bool operator==(const self &s) {
                return _node == s._node;
            }
    
            // 拷贝构造和析构不需要写,析构不能用,不然结点被删除了
    
            // 比如 lt.begin(),这里的类型就是Node*
            Node *_node; // 内置类型不能重载++等操作符,因此对这个内置类型进行封装来实现++等功能
        };
    
    //    template<class T>
    //    class __list_const_iterator {
    //    public:
    //        typedef ListNode<T> Node;
    //        typedef __list_const_iterator<T> self; // 迭代器本身
    //
    //        // 这里构造函数为了方便begin和end,直接隐式类型转换
    //        __list_const_iterator(Node *node) : _node(node) {
    //
    //        }
    //
    //        const T &operator*() {
    //            return _node->data;
    //        }
    //
    //        self &operator++() {
    //            _node = _node->_next;
    //            return *this;
    //        }
    //
    //        self operator++(int) {
    //            self temp(*this); // 这里*this的类型是self ,调用默认拷贝构造函数!因为是内置类型,不需要自己写
    //            _node = _node->_next;
    //            return temp;
    //        }
    //
    //        self &operator--() {
    //            _node = _node->_prev;
    //            return *this;
    //        }
    //
    //        self &operator--(int) {
    //            self temp(*this);
    //            _node = _node->_prev;
    //            return temp;
    //        }
    //
    //        bool operator!=(const self &s) {
    //            return _node != s._node;
    //        }
    //
    //        bool operator==(const self &s) {
    //            return _node == s._node;
    //        }
    //
    //        // 拷贝构造和析构不需要写,析构不能用,不然结点被删除了
    //
    //        // 比如 lt.begin(),这里的类型就是Node*
    //        Node *_node; // 内置类型不能重载++等操作符,因此对这个内置类型进行封装来实现++等功能
    //    };
    
        template<class T>
        class list {
        public:
            typedef ListNode<T> Node;
            typedef __list_iterator<T, T &, T *> iterator;
            typedef __list_iterator<T, const T &, const T *> const_iterator;
    
            typedef ReverseIterator<iterator, const T &, const T *> reverse_iterator;
            typedef ReverseIterator<const_iterator, const T &, const T *> const_reverse_iterator;
    
            //构造函数
            list() {
                //创建带头节点的双向循环链表
                _head = new Node;
                _head->_next = _head;
                _head->_prev = _head;
            }
    
            // 拷贝构造函数
            list(list<T> &lt) {
                // 先创个头节点
                _head = new Node;
                _head->_next = _head;
                _head->_prev = _head;
    
                iterator it = lt.begin();
                while (it != lt.end()) {
                    push_back(*it);
                    ++it;
                }
            }
    
            void swap(list<T> &lt) {
                std::swap(_head, lt._head);
            }
    
            // 赋值
            list<T> operator=(list<T> lt) {
                swap(lt);
                return *this;
            }
    
            iterator begin() {
                return _head->_next;
            }
    
            iterator end() {
                return _head;
            }
    
            const_iterator begin() const {
                return _head->_next;
            }
    
            const_iterator end() const {
                return _head;
            }
    
            reverse_iterator rbegin() {
                return end();
            }
    
            reverse_iterator rend() {
                return begin();
            }
    
            const_reverse_iterator rbegin() const {
                return end();
            }
    
            const_reverse_iterator rend() const {
                return begin();
            }
    
            void push_back(const T &val) {
    //            Node *tail = _head->_prev;// 先找到尾
    //
    //            // 创建新节点
    //            Node *newnode = new Node(val);
    //
    //            tail->_next = newnode;
    //            newnode->_prev = tail;
    //
    //            newnode->_next = _head;
    //            _head->_prev = newnode;
    
                insert(end(), val);
            }
    
            iterator insert(iterator pos, const T &val) {
    
                Node *cur = pos._node;
                Node *prev = cur->_prev;
                Node *newnode = new Node(val);
    
                newnode->_next = cur;
                newnode->_prev = prev;
                prev->_next = newnode;
                cur->_prev = newnode;
    
                return newnode;
            }
    
            iterator erase(iterator pos) {
                assert(pos != _head);// _head这个位置就是end()
    
                Node *cur = pos._node;
                Node *prev = cur->_prev;
                Node *tail = cur->_next;
    
                prev->_next = tail;
                tail->_prev = prev;
    
                delete cur;
    
                return tail;
            }
    
            void clear() {
                // 清空所有数据,只留一个头节点
                iterator it = begin();
                while (it != end()) {
                    it = erase(begin());
                }
            }
    
            ~list() {
                clear();
                if (_head) {
                    delete _head;
                    _head = nullptr;
                }
    
            }
    
        private:
            Node *_head;// 头节点 -- 带头双向循环链表
        };
    
        void test_list1() {
            list<int> lt;
            lt.push_back(1);
            lt.push_back(2);
            lt.push_back(3);
            lt.push_back(4);
            lt.push_back(5);
    
            list<int>::iterator it = lt.begin();
            while (it != lt.end()) {
                cout << *it << " ";
                it++;
            }
            cout << endl;
    
            lt.insert(lt.begin(), 10);
            lt.insert(lt.begin(), 20);
            lt.insert(lt.begin(), 30);
    
            for (auto e: lt) {
                cout << e << " ";
            }
            cout << endl;
    
            lt.erase(--lt.end());
            lt.erase(--lt.end());
            for (auto e: lt) {
                cout << e << " ";
            }
            cout << endl;
    
            lt.clear();
            for (auto e: lt) {
                cout << e << " ";
            }
            cout << endl;
        }
    
        void test_list2() {
            list<int> lt;
            lt.push_back(1);
            lt.push_back(2);
            lt.push_back(3);
            lt.push_back(4);
            lt.push_back(5);
    
            list<int> lt1(lt);
            for (auto e: lt1) {
                cout << e << " ";
            }
            cout << endl;
    
            list<int> lt2 = lt;
            for (auto e: lt2) {
                cout << e << " ";
            }
            cout << endl;
        }
    
    
        //  测试const迭代器
        void Print_list(const list<int> &lt) {
            list<int>::const_iterator it = lt.begin();
    
            while (it != lt.end()) {
                cout << *it << " ";
                ++it;
            }
            cout << endl;
        }
    
        void test_list3() {
            list<int> lt;
            lt.push_back(1);
            lt.push_back(2);
            lt.push_back(3);
            lt.push_back(4);
            lt.push_back(5);
    
            for (auto e: lt) {
                cout << e << " ";
            }
            cout << endl;
    
            Print_list(lt);
        }
    
    
        // 测试list重载->运算符
        struct AA {
            AA(int a1 = 3, int a2 = 4) : _a1(a1), _a2(a2) {
    
            }
    
            int _a1 = 1;
            int _a2 = 2;
        };
    
        void test_list4() {
            list<AA> lt;
            lt.push_back(AA());
            lt.push_back(AA(2, 1));
            lt.push_back(AA(5, 5));
    
            list<AA>::iterator it = lt.begin();
            while (it != lt.end()) {
                cout << (*it)._a1 << " " << (*it)._a2 << endl;
                cout << it->_a1 << " " << it->_a2 << endl;
                cout << it.operator->()->_a1 << " " << it.operator->()->_a2 << endl;//原型,即运算符重载->省略了一个->
                ++it;
            }
        }
    
        void test_list5() {
            list<int> lt;
            lt.push_back(1);
            lt.push_back(2);
            lt.push_back(3);
            lt.push_back(4);
            lt.push_back(5);
    
            list<int>::reverse_iterator rit = lt.rbegin();
            while (rit != lt.rend()) {
                cout << *rit << " ";
                ++rit;
            }
            cout << endl;
        }
    }
    
  • ReverseIterator.h文件

    //
    // Created by 徐鹏 on 2024/3/11.
    //
      
    #ifndef DEMO_05_REVERSEITERATOR_H
    #define DEMO_05_REVERSEITERATOR_H
      
    #endif //DEMO_05_REVERSEITERATOR_H
    
    
    template<class Iterator, class Ref, class Ptr>
    struct ReverseIterator {
        typedef ReverseIterator<Iterator, Ref, Ptr> self;
    
        ReverseIterator(Iterator it) : _it(it) {
        
        }
    
    
        // 这里我们采用和正向迭代器对称的结构
        Iterator _it;
        
        Ref operator*() {
            Iterator tmp = _it;// 不能改变_it的位置,用tmp来指向_it的位置,来改变tmp的位置
            --tmp;
            return *tmp;
        }
        
        Ptr operator->() {
            return &(operator*());
        }
        
        self &operator++() {
            --_it;
            return *this;
        }
        
        self operator++(int) {
            self tmp(*this);
            --_it;
            return tmp;
        }
        
        self &operator--() {
            ++_it;
            return *this;
        }
        
        self operator--(int) {
            self tmp(*this);
            ++_it;
            return tmp;
        }
        
        bool operator!=(const self &s) {
            return _it != s._it;
        }
        
        bool operator==(const self &s) {
            return _it == s._it;
        }
    };
    
  • main.cpp文件

    #include "list.h"
    
    int main() {
    //    xp::test_list1();
    //    xp::test_list2();
    //    xp::test_list3();
    //    xp::test_list4();
        xp::test_list5();
        return 0;
    }
    

OKOK,C++ STL容器之list类就到这里。如果你对Linux和C++也感兴趣的话,可以看看我的主页哦。下面是我的github主页,里面记录了我的学习代码和leetcode的一些题的题解,有兴趣的可以看看。

Xpccccc的github主页

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/464370.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

五、保持长期高效的七个法则(二)Rules for Staying Productive Long-Term(1)

For instance - lets say youre a writer.You have a bunch of tasks on your plate for the day, but all of a sudden you get a really good idea for an essay. You should probably start writing now or youll lose your train of thought.What should you do? 举例来说…

rust引用本地crate

我们可以动态引用crate&#xff0c;build时从crate.io下载&#xff0c;但可能因无法下载导致build失败。首次正常引用三方crate&#xff0c;build时自动下载的crate源码&#xff0c;我们将其拷贝到固定目录中&#xff1b; build后可在RustRover中按住Ctrl键&#xff0c;在crat…

【Linux】环境基础开发工具使用

目录 Linux软件管理器 yum 1.什么是软件包 2.查看软件包 3安装与卸载 vim-Linux编辑器 1.vim基础概念 2.vim的基础操作 命令模式基本操作 底层模式基本操作 3、其它模式 Linux编译器 gcc/g 1.如何进行编译 2.编译的四个过程 预处理(-E) 编译(-S) 汇编(-c) 链接…

代码算法训练营day10 | 232.用栈实现队列、225. 用队列实现栈

day10: 232.用栈实现队列225. 用队列实现栈 232.用栈实现队列 题目链接 状态&#xff1a; 文档&#xff1a;programmercarl.com 思路&#xff1a; 用栈实现队列。要先明白两者的区别。 栈&#xff1a;单开门&#xff0c;先进后出&#xff0c;只有一端能进出。 队列&#xff1a;…

【论文笔记合集】LSTNet之循环跳跃连接

本文作者&#xff1a; slience_me LSTNet 循环跳跃连接 文章仅作为个人笔记 论文链接 文章原文 LSTNet [25] introduces convolutional neural networks (CNNs) with recurrent-skip connections to capture the short-term and long-term temporal patterns. LSTNet [25]引入…

1、鸿蒙学习-为应用/服务进行签名

针对应用/服务的签名&#xff0c;DevEco Studio为开发者提供了自动签名方案&#xff0c;帮助开发者高效进行调试。也可选择手动方式对应用/服务进行签名&#xff0c;如果使用了需要ACL的权限&#xff0c;需采用手动方式进行签名。 自动签名 说明 使用自动签名前&#xff0c;请…

简单!实用!易懂!:Java如何批量导出微信收藏夹链接-->转换成Markdown/txt

文章目录 前言参考方案方案1&#xff1a;Python方案2&#xff1a;Python 我的方案手动前置操作代码处理 前言 不知道是否有很多小伙伴跟我一样&#xff0c;有个问题非常愁&#xff0c;对于收藏党来说&#xff0c;收藏了学会了&#xff01;然后导致微信收藏夹的东西越来越多了&…

2024年5家香港服务器推荐,性价比top5

​​香港服务器是中小企业建站、外贸建站、个人博客建站等领域非常受欢迎的服务器&#xff0c;2024年有哪些云厂商的香港服务器是比较有性价比的&#xff1f;这里根据小编在IT领域多年服务器使用经验&#xff0c;给大家罗列5家心目中最具性价比的香港服务器厂商。 这五家香港服…

Wireshark抓包工具的使用

提示&#xff1a;本文为学习记录&#xff0c;若有错误&#xff0c;请联系作者&#xff0c;谦虚受教 文章目录 前言一、下载二、首页三、使用1.读入数据2.分析数据3.筛选IP4.保存数据 四、过滤器表达式五、TCP总结 前言 低头做事&#xff0c;抬头看路。 一、下载 下载路径wire…

Java面试题总结200道(三)

51、什么是 Spring IOC 容器 Spring 框架的核心是 Spring 容器。容器创建对象&#xff0c;将它们装配在一起&#xff0c;配置它 们并管理它们的完整生命周期。Spring 容器使用依赖注入来管理组成应用程序的 组件。容器通过读取提供的配置元数据来接收对象进行实例化&#xff0…

【vue video.js】The element or ID supplied is not valid. (videojs) element Ui

问题&#xff1a;使用video.js做了一个弹窗显示视频&#xff0c;效果如下 但是发现弹窗再次打开&#xff0c;视频播放失败&#xff0c;报错The element or ID supplied is not valid 原因是videojs找不到需要初始化的视频id&#xff0c;在关闭弹窗的时候需要重置video.js&…

小迪安全42WEB攻防-通用漏洞文件包含LFIRFI伪协议

#知识点: 1、解释什么是文件包含 2、分类-本地LFI&远程RFI 3、利用-配合上传&日志&会话 4、利用-伪协议&编码&算法等 #核心知识: 1、本地包含LFI&远程包含RF1-区别 一个只能包含本地&#xff0c;一个可以远程加载 具体形成原因由代码和环境配置文件决定…

便利店小程序有哪些功能

​便利店小程序为附近的住户提供小程序在线购物的服务。用户只需要打开小程序&#xff0c;就可以购买需要的商品&#xff0c;可以选择自取或者配送。整个过程非常简单快速。下面具体介绍便利店小程序的功能。 1. **商品展示**&#xff1a;展示便利店的商品信息&#xff0c;包括…

芯片顶级盛会HotChip历年-未来芯片论坛及资料全集下载

提示&#xff1a;下载链接在文章最后。 Hotchips是全球芯片行业影响力最大的会议。 Hot Chips是一个技术会议&#xff0c;聚焦于半导体和微处理器的设计与创新。以下是一些关于Hot Chips的信息和相关链接&#xff1a; Hot Chips会议官方网站&#xff1a;https://www.hotchips…

Prometheus 基于 Consul 实现服务自动发现注册

文章目录 一、概述二、docker-compose 部署 Prometheus1&#xff09;部署 docker2&#xff09;部署 docker-compose3&#xff09;配置 prometheus.yml4&#xff09;配置 rules.yml5&#xff09;配置 alertmanager.yml6&#xff09;编排 docker-compose yaml 文件7&#xff09;开…

【Windows Defender 排除指定 文件夹、文件夹以提升性能】

使用webStorm时候提醒排出程序和目录提升性能, 于是我就把我的代码目录和常用程序全部排出, 不过不知道能不能提升多少性能, 先加上再说 一.使用UI配置排出项 隐私与安全性安全中心 病毒与威胁防护 添加或删除排出项 配置 二.使用命令配置 使用 PowerShell开启自动排除列表…

Redis数据结构对象之字符串对象

字符串对象 字符串对象的编码可以是int、raw或者embstr 如果一个字符串对象保存的是整数值&#xff0c;并且这个整数值可以用long类型来表示&#xff0c;那么字符串对象会将整数值保存在字符串对象结构的ptr属性里面(将void *转换成long)&#xff0c;并且将字符串对象的编码设…

面试算法-39-删除链表的倒数第 N 个结点

题目 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 解 class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {L…

在idea中配置tomcat服务器,然后部署一个项日

1.下载tomcat Tomcat下载 点击右边的tomcat8 找到zip点击下载 下载完&#xff0c;解压到你想放置的路径下 2.配置环境变量 打开设置找到高级系统设置点击环境变量 点击新建&#xff0c;变量名输入&#xff1a;CATALINA_HOME&#xff0c;变量值就是Tomcat的安装路径&#x…

空间计算综合指南

空间计算&#xff08;spatial computing&#xff09;是指使人类能够在三维空间中与计算机交互的一组技术。 该保护伞下的技术包括增强现实&#xff08;AR&#xff09;和虚拟现实&#xff08;VR&#xff09;。 这本综合指南将介绍有关空间计算所需了解的一切。 你将了解 AR、VR…