STL容器之list类

news2025/6/23 13:45:05

文章目录

  • 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.coloradmin.cn/o/1524385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++初阶:1_C++入门

C入门 零.本节知识点安排目的 C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式等。熟悉C语言之后&#xff0c;对C学习有一定的帮助&#xff0c;本章节主要目标&#xff1a; 补充C语言语法的不足&#xff0…

【S5PV210_视频编解码项目】裸机开发:实现按键的外部中断处理

加粗样式本文所作内容&#xff1a; 基于S5PV210芯片实现按键的外部中断处理程序&#xff0c;搭建中断处理流程框架 S5PV210对于中断处理的操作流程 1 外部中断得到触发&#xff1a; 1&#xff09;外部中断在初始化阶段得到使能 2&#xff09;外界达到了外部中断的触发条件 …

Spring注解方式整合三层架构

注解方式特点 1. 完全注解方式指的是去掉xml文件&#xff0c;使用配置类 注解实现 2. xml文件替换成使用Configuration注解标记的类 3. 标记IoC注解&#xff1a;Component,Service,Controller,Repository 4. 标记DI注解&#xff1a;Autowired Qualifier Resource Value 5. &…

html--简历

文章目录 html html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"maximum-scale1.0,minimum-scale1.0,user-scalable0,widthdevice-width,initial-scale1.0&qu…

SqlServer2008(R2)(二)SqlServer2008(R2)安装和卸载注意事项整理

二、注意事项 1、 安装数据中心版 说明&#xff1a;此激活版仅用于测试和学习使用。 这是官方的下载页面&#xff08;需要付费订阅&#xff09;&#xff1a; http://msdn.microsoft.com/zh-cn/subscriptions/downloads/default.aspx 数据中心版&#xff1a; PTTFM-X467G-P7RH…

在Windows系统上搭建MongoDB-这篇文章刚刚好

在Windows系统上搭建MongoDB集群 文章目录 1.下载MongoDB2.集群描述3.构建集群文件目录4.新建配置文件5.启动MongoDB服务6.配置集群7.集群测试8.设置密码和开启认证一、安装MongoDB 1.下载MongoDB 去MongoDB官网下载解压版免安装的压缩包。 https://www.mongodb.com/try/do…

金枪鱼群优化算法TSO优化BiLSTM-ATTENTION实现风力发电功率预测(matlab)

金枪鱼群优化算法TSO优化BiLSTM-ATTENTION实现风力发电功率预测&#xff08;matlab&#xff09; TSO-BiLSTM-Attention金枪鱼群算法优化长短期记忆神经网络结合注意力机制的数据回归预测 Matlab语言。 金枪鱼群优化算法&#xff08;Tuna Swarm Optimization&#xff0c;TSO)是一…

一种动态联动的实现方法

安防领域中的联动规则 有安防领域相关的开发经历的人知道&#xff0c;IPCamera可以配置使能“侦测”功能&#xff0c;并且指定仅针对图像传感器的某个区载进行侦测。除了基本的“移动侦测"外&#xff0c;侦测的功能点还有细化的类别&#xff0c;如人员侦测、车辆侦测、烟…

python之前端css样式(一)

css ID选择器 #c1{color:red;#边框为红色border:1px solid red; } <div id"c2">中国移动</div> 类选择器 .xx{color:blue; } <div class"xx">中国联通</div> 标签选择器 li{color: pink; } <ul><li>北京</li…

C++作业day4

成员函数版本实现算术运算符的重载 全局函数版本实现算术运算符的重载 #include <iostream>using namespace std;class Person {friend const Person operator-(const Person &L,const Person &R); private:int a;int b; public:Person() {}Person(int a,int …

网康科技 NS-ASG 应用安全网关 SQL注入漏洞复现(CVE-2024-2330)

0x01 产品简介 网康科技的NS-ASG应用安全网关是一款软硬件一体化的产品,集成了SSL和IPSec,旨在保障业务访问的安全性,适配所有移动终端,提供多种链路均衡和选择技术,支持多种认证方式灵活组合,以及内置短信认证、LDAP令牌、USB KEY等多达13种认证方式。 0x02 漏洞概述 …

深入浅出ConcurrentHashMap

ConcurrentHashMap 由于HashMap在多线程的环境下有线程安全的问题&#xff0c;并且HashTable的性能低下&#xff0c;所以Java推出了ConcurrentHashMap&#xff0c;因此ConcurrentHashMap可以理解为线程安全并且性能较好的HashMap。 HashTable为什么慢&#xff1f;是因为使用了…

同步和异步程序的关联和区别是?Guide to Synchronous and Asynchronous Code

2024/3/12 发布 正在寻觅一份前端开发工作&#xff0c;如果您觉得这篇文章对你有所帮助&#xff0c;这是我的简历1 在这篇文章中你能学习和理解&#xff1a;NodeJS是如何工作、如何处理所有发送给服务器的函数&#xff08;无论同步或者异步&#xff09;和请求、Event Loops in …

Apache-Doris基础概念

OLAP数据库Doris 一、Doris架构二、基本概念1. Row & Column2. Partition & Tablet3. 建表示例&#xff08;1&#xff09;列的定义&#xff08;2&#xff09;分区分桶&#xff08;3&#xff09;多列分区&#xff08;4&#xff09;PROPERTIES&#xff08;5&#xff09;E…

Java 面试题之框架

1. Spring 是什么 Sping 是包含了众多工具方法的 IOC 容器&#xff0c;IOC是控制反转&#xff0c;说的是对象的创建和销毁的权利都交给 Spring 来管理了, 它本身又具备了存储对象和获取对象的能力. 。 容器&#xff1a;字面意思&#xff0c;用来容纳某种物品的装置。 比如 L…

通俗易懂的Python循环讲解

循环用于重复执行一些程序块。从上一讲的选择结构&#xff0c;我们已经看到了如何用缩进来表示程序块的隶属关系。循环也会用到类似的写法。 for循环 for循环需要预先设定好循环的次数(n)&#xff0c;然后执行隶属于for的语句n次。 基本构造是 for 元素 in 序列: statemen…

RoketMQ主从搭建

vim /etc/hosts# IP与域名映射&#xff0c;端口看自己的#nameserver 192.168.126.132 rocketmq-nameserver1 192.168.126.133 rocketmq-nameserver2# 注意主从节点不在同一个主机上 #broker 192.168.126.132 rocketmq-master1 192.168.126.133 rocketmq-master2#broker 192.168…

网络通信.

1.物理层&#xff1a;网络通信的基础设施 运快递的公路 2.数据链路层 两个相邻的节点之间如何传输 两个集散点之间的传输 3.网络层 两个点之间的路径规划 物流公司规划快递的路径 4.传输层 两个点之间的通信&#xff08;不考虑路径规划&#xff09; 卖家发货 只考虑起点和终点 …

C++ 特殊类及单例模式

文章目录 1. 前言2. 不能被拷贝的类3. 不能被继承的类4. 只能在堆上创建对象的类5. 只能在栈上创建对象的类6. 只能创建一个对象的类&#xff08;单例模式&#xff09; 1. 前言 在实际场景中&#xff0c;我们在编写类的过程中总会遇到一些特殊情况&#xff0c;比如设计一个类不…

【Godot4.0】自定义A*寻路拓展类TileMapAStar2D及其使用

概述 Godot提供的AStar2D和AStarGrid2D基本可以解决所有2D的A*寻路问题&#xff1a; 前者提供了基础的A*寻路支持&#xff0c;但是需要手动处理很多内容后者针对基于方形图块的A*寻路&#xff0c;进行了很多自动化的工作&#xff0c;用起来十分简便。但是不使用于六边形、iso…