欢迎来到C++领域第十八幕!今天我们将深入探讨STL中的list容器,从了解到使用,最后手撕模拟实现,带你彻底掌握这一重要容器。无论你是C++初学者还是有一定经验的开发者,相信这篇文章都能让你对list有更深刻的理解。
STL list容器是C++标准模板库中的序列式容器之一,其底层实现为双向循环链表。与vector的连续内存不同,list的元素在内存中分散存储,通过指针链接。这使得list在任意位置插入和删除元素都非常高效(O(1)时间复杂度),但缺点是无法随机访问元素(不支持operator[]),只能通过迭代器顺序访问。list非常适合频繁插入删除的场景,如实现LRU缓存、任务队列等。
上图展示了list的双向链表结构,每个节点包含数据域data、前驱指针prev和后继指针next。通过头节点(哨兵)可以快速访问首尾元素。
list提供了多种构造函数:默认构造、填充构造、范围构造、拷贝构造等。下面是一些示例:
#include std::list l1; // 空liststd::list l2(5, 10); // 5个10std::list l3(l2.begin(), l2.end()); // 迭代器范围std::list l4(l3); // 拷贝构造std::list l5 = {1,2,3,4,5}; // C++11初始化列表
赋值操作可使用operator=或assign成员函数:l1 = l2; l1.assign(3, 100); 等。
list的成员函数非常丰富,下面分类介绍C++ list使用中的常见操作:
例如:l.push_back(42); l.pop_front(); l.insert(++l.begin(), 99);
list迭代器属于双向迭代器,支持++和--操作,但不支持随机访问(如it+5)。list的迭代器不会因为插入或其他删除(除非指向被删元素)而失效,这一点与vector不同。使用迭代器遍历list:
for(auto it = l.begin(); it != l.end(); ++it) { std::cout << *it << " ";} list还提供反向迭代器rbegin/rend。
理解了list的原理后,我们可以尝试list模拟实现,以加深对底层机制的理解。下面是一个简化版的mylist,包含节点结构、迭代器封装和基本操作。注意:为了清晰,省略了一些异常安全和C++11特性。
template struct ListNode { T data; ListNode* prev; ListNode* next; ListNode(const T& val = T(), ListNode* p = nullptr, ListNode* n = nullptr) : data(val), prev(p), next(n) {}};template class ListIterator {public: using iterator_category = std::bidirectional_iterator_tag; using value_type = T; using difference_type = ptrdiff_t; using pointer = T; using reference = T&; ListNode ptr; ListIterator(ListNode* p = nullptr) : ptr(p) {} reference operator*() const { return ptr->data; } pointer operator->() const { return &(ptr->data); } ListIterator& operator++() { ptr = ptr->next; return *this; } ListIterator operator++(int) { ListIterator tmp = this; ++(this); return tmp; } ListIterator& operator--() { ptr = ptr->prev; return this; } ListIterator operator--(int) { ListIterator tmp = this; --(this); return tmp; } bool operator==(const ListIterator& other) const { return ptr == other.ptr; } bool operator!=(const ListIterator& other) const { return ptr != other.ptr; }};template class mylist { using Node = ListNode; Node head; // 哨兵节点,head->next指向第一个元素,head->prev指向最后一个元素 size_t sz;public: using iterator = ListIterator; using const_iterator = ListIterator; // 简化,实际需要区分 mylist() : head(new Node()), sz(0) { head->prev = head; head->next = head; } ~mylist() { clear(); delete head; } void clear() { while (!empty()) pop_front(); } bool empty() const { return sz == 0; } size_t size() const { return sz; } iterator begin() { return iterator(head->next); } iterator end() { return iterator(head); } const_iterator begin() const { return const_iterator(head->next); } const_iterator end() const { return const_iterator(head); } void push_front(const T& val) { insert(begin(), val); } void push_back(const T& val) { insert(end(), val); } void pop_front() { erase(begin()); } void pop_back() { erase(--end()); } iterator insert(iterator pos, const T& val) { Node* cur = pos.ptr; Node* prev = cur->prev; Node* newNode = new Node(val, prev, cur); prev->next = newNode; cur->prev = newNode; ++sz; return iterator(newNode); } iterator erase(iterator pos) { Node* cur = pos.ptr; if (cur == head) return end(); // 不能删除哨兵 Node* prev = cur->prev; Node* next = cur->next; prev->next = next; next->prev = prev; delete cur; --sz; return iterator(next); } // 其他功能如拷贝构造、赋值运算符等省略}; 上述代码实现了list的核心框架,包括迭代器和基本插入删除。通过模拟实现,我们可以更清晰地理解list的内存管理和迭代器原理。
本文详细介绍了STL list容器的概念、构造、常用操作、迭代器以及手撕模拟实现。list作为双向链表,在频繁插入删除的场景下具有显著优势,但需注意其不支持随机访问的特点。希望通过本教程,你对list有了更全面的掌握,能够灵活运用并理解其底层原理。
本文关键词:STL list容器 C++ list使用 list迭代器 list模拟实现
本文由主机测评网于2026-02-17发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/20260225541.html