【C++】“list”的介绍和常用接口的模拟实现

#include<assert.h> #include<iostream> using std::cout; using std::endl; namespace wch { //由于list中的val支持多种类型,定义模板参数T template<class T> struct list_node { list_node<T>* _next; list_node<T>* _prev; T _val; //T(),针对自定义类型会去调用它的构造函数,针对内置类型无影响 list_node(const T& val = T()) :_next(nullptr) , _prev(nullptr) , _val(val) {} }; // typedef __list_iterator<T, T&, T*> iterator; // typedef __list_iterator<T, const T&, const T*> const_iterator; //此处定义多个模板参数针对返回值类型 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) {} Ref operator*() const//重载普通对象解引用 { return _node->_val; } Ptr operator->() const//重载指针对象解引用 { return &_node->_val; } self& operator++()//返回对象在函数体执行结束后依旧存在,建议引用返回,减少拷贝开销 { _node = _node->_next; return *this; } //返回对象(局部变量或指向局部变量的指针)在函数体执行结束后不存在,不可引用返回,值返回 self operator++(int) { self tmp(*this); _node = _node->_next; return tmp; } self& operator--() { _node = _node->_prev; return *this; } self operator--(int) { self tmp(*this); _node = _node->_prev; return tmp; } //尽量使用引用形参, 避免拷贝开销。同时在不需要修改实参时,通过指定const 引用形参来限制。 bool operator!=(const self& it) const { return _node != it._node; } bool operator==(const self& it) const { return _node == it._node; } }; template<class T> class list { typedef list_node<T> Node; public: typedef __list_iterator<T, T&, T*> iterator; typedef __list_iterator<T, const T&, const T*> const_iterator; // 这样设计const迭代器是不行的,因为const迭代器期望指向内容不能修改 // 这样设计是迭代器本身不能修改 // T* const ptr2; iterator begin() { //return _head->_next;//单参构造函数支持隐式类型转换 return iterator(_head->_next); } iterator end() { return _head;//单参构造函数支持隐式类型转换 //return iterator(_head); } const_iterator begin() const { //return _head->_next; return const_iterator(_head->_next); } const_iterator end() const { return _head; //return const_iterator(_head); } void empty_init() { _head = new Node; _head->_prev = _head; _head->_next = _head; _size = 0; } list()//无参默认构造函数 { empty_init(); } // lt2(lt1) list(const list<T>& lt)//拷贝构造 //list(const list& lt)//不加类型也可以,不建议 { empty_init(); for (auto& e : lt)//深拷贝 { push_back(e); } } void swap(list<T>& lt) { std::swap(_head, lt._head); std::swap(_size, lt._size); } list<T>& operator=(list<T> lt)//赋值运算符重载 //list& operator=(list lt)//不加类型也可以,不建议 { swap(lt); return *this; } ~list()//析构函数 { clear(); delete _head; _head = nullptr; } void clear() { iterator it = begin(); while (it != end()) { it = erase(it);//带位置返回值的erase函数,防止迭代器失效 } _size = 0; } void push_back(const T& x) { insert(end(), x); } void push_front(const T& x) { insert(begin(), x); } void pop_back() { erase(--end()); } void pop_front() { erase(begin()); } // pos位置之前插入 iterator insert(iterator pos, const T& x) { Node* cur = pos._node; Node* prev = cur->_prev; Node* newnode = new Node(x); prev->_next = newnode; newnode->_next = cur; cur->_prev = newnode; newnode->_prev = prev; ++_size; return newnode; } //删除pos处节点 iterator erase(iterator pos) { assert(pos != end());//不可删除头节点 Node* cur = pos._node; Node* prev = cur->_prev; Node* next = cur->_next; prev->_next = next; next->_prev = prev; delete cur; --_size; return next; } size_t size() { /*size_t sz = 0; iterator it = begin(); while (it != end()) { ++sz; ++it; } return sz;*/ return _size; } private: Node* _head; size_t _size; }; void Print(const list<int>& lt) { list<int>::const_iterator it = lt.begin(); while (it != lt.end()) { //(*it) += 1; cout << *it << " "; ++it; } cout << endl; } void test_list1() { list<int> lt; lt.push_back(1); lt.push_back(2); lt.push_back(3); lt.push_back(4); list<int>::iterator it = lt.begin(); //由于链表的各个节点地址是不连续的,前一个节点的地址可能比后一个地址大,所以不可已写为 it < it.end(); while (it != lt.end()) { (*it) += 1; cout << *it << " "; ++it; } cout << endl; for (auto e : lt) { cout << e << " "; } cout << endl; Print(lt); } struct A { A(int a1 = 0, int a2 = 0) :_a1(a1) , _a2(a2) {} int _a1; int _a2; }; void test_list2() { list<A> lt; lt.push_back(A(1, 1)); lt.push_back(A(2, 2)); lt.push_back(A(3, 3)); lt.push_back(A(4, 4)); list<A>::iterator it = lt.begin(); while (it != lt.end()) { //cout << (*it)._a1 << " " << (*it)._a2 << endl; //it->->_a1, it->->_a2,特殊处理为一个-> cout << it->_a1 << " " << it->_a2 << endl; ++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_front(5); lt.push_front(6); lt.push_front(7); lt.push_front(8); for (auto e : lt) { cout << e << " "; } cout << endl; lt.pop_front(); lt.pop_back(); for (auto e : lt) { cout << e << " "; } cout << endl; lt.clear(); lt.push_back(10); lt.push_back(20); lt.push_back(30); lt.push_back(40); for (auto e : lt) { cout << e << " "; } cout << endl; cout << lt.size() << endl; } void test_list4() { list<int> lt; lt.push_back(1); lt.push_back(2); lt.push_back(3); lt.push_back(4); for (auto e : lt) { cout << e << " "; } cout << endl; list<int> lt1(lt); for (auto e : lt1) { cout << e << " "; } cout << endl; list<int> lt2; lt2.push_back(5); lt2.push_back(6); lt2.push_back(7); lt2.push_back(8); for (auto e : lt2) { cout << e << " "; } cout << endl; lt1 = lt2; for (auto e : lt1) { cout << e << " "; } cout << endl; } }
上一篇:FreeRTOS篇4:任务调度


下一篇:简单理解程序地址空间:Linux 中的内存映射与页表解析