C++STL--list底层实现,迭代器分类,模拟list的迭代器封装、实现


博主名称:deM0one ⭐️C++专栏: C++

文章目录

  • [C++ STL list 容器底层原理:从零实现一个类 STL 的 list](#C++ STL list 容器底层原理:从零实现一个类 STL 的 list)
    • 一、引言
    • 二、迭代器类型与性能特性
      • [2.1 迭代器类型](#2.1 迭代器类型)
      • [2.2 性能特点](#2.2 性能特点)
      • [2.3 支持双向迭代器的容器](#2.3 支持双向迭代器的容器)
    • [三、vector 的成员类型详解](#三、vector 的成员类型详解)
    • 四、迭代器分类体系
    • [五、list 的内部结构设计](#五、list 的内部结构设计)
      • [5.1 循环双向链表 + 哨兵节点](#5.1 循环双向链表 + 哨兵节点)
      • [5.2 push_back 实现](#5.2 push_back 实现)
    • 六、迭代器的封装与实现
      • [6.1 普通人的写法(不封装迭代器)](#6.1 普通人的写法(不封装迭代器))
      • [6.2 仿 STL 的迭代器封装](#6.2 仿 STL 的迭代器封装)
    • 七、总结
    • 附录:参考资料

C++ STL list 容器底层原理:从零实现一个类 STL 的 list

一、引言

  • C++ STL(Standard Template Library)是 C++ 标准库的核心组件
  • list 作为双向链表容器,与 vector 等顺序容器有本质区别
  • 本文将从迭代器类型、内部结构、关键操作实现、迭代器封装四个维度,深度解析 list 的工作原理

二、迭代器类型与性能特性

2.1 迭代器类型

类型 说明
iterator 普通迭代器,支持读写
reverse_iterator 反向迭代器,从尾部向前遍历
const_iterator 常量迭代器,只读访问
const_reverse_iterator 常量反向迭代器

2.2 性能特点

  • 支持双向遍历 :可通过 ++-- 操作前后移动
  • 不支持随机访问 :无 operator[],不能通过下标直接访问元素
  • 时间复杂度:
    • 插入/删除:O(1)(已知位置)
    • 查找:O(n)

2.3 支持双向迭代器的容器

  • listmapmultimap
  • setmultiset
  • vectorstringdeque(这些支持随机访问迭代器)

注意:STL 从 C++98 起就支持上述迭代器类型。


三、vector 的成员类型详解

std::vector<T, Alloc> 为例,其成员类型定义如下:

成员类型 定义
value_type 模板第一个参数 T
allocator_type 模板第二个参数 Alloc
reference allocator_type::reference
const_reference allocator_type::const_reference
pointer allocator_type::pointer
const_pointer allocator_type::const_pointer
iterator 指向 value_type 的随机访问迭代器
const_iterator 指向 const value_type 的随机访问迭代器
reverse_iterator reverse<iterator>
size_type 无符号整数类型

关键点vector 的迭代器是随机访问迭代器 ,而 list 的迭代器仅为双向迭代器


四、迭代器分类体系

复制代码
Input ← Output ← Forward ← Bidirectional ← Random Access
迭代器类型 能力说明
Input Iterator 只读、单向、只能前进一次
Forward Iterator 可读写、可多次遍历同一元素
Bidirectional Iterator 可前可后移动(listmap 使用)
Random Access Iterator 支持任意位置跳跃(vectordeque 使用)

五、list 的内部结构设计

5.1 循环双向链表 + 哨兵节点

list 内部采用循环双向链表结构,并设置一个**哨兵节点(sentinel)**作为头节点。

cpp 复制代码
protected:
    link_type node;  // 哨兵节点指针

public:
    list() { empty_initialize(); }

void empty_initialize() {
    node = get_node();      // 分配哨兵节点
    node->next = node;      // 自循环
    node->prev = node;
}

设计意义:哨兵节点简化了边界处理,使得空链表和非空链表的处理逻辑保持一致。

5.2 push_back 实现

cpp 复制代码
void push_back(const T& x) {
    Node* newnode = new Node(x);
    Node* tail = _head->prev;   // 当前尾节点
    tail->next = newnode;       // 原尾部指向新节点
    newnode->prev = tail;       // 新节点指回原尾部
    newnode->next = _head;      // 新节点指向哨兵
    _head->prev = newnode;      // 哨兵指回新节点
}

插入过程图示:

复制代码
         tail        newnode
            ↓           ↓
[head] ←── 1 ←── 2 ←── 3 ←── 4
            ↑           ↑
           head       newnode
  • 在链表尾部插入新节点 newnode
  • 更新原尾节点 tailnext 指向新节点
  • 新节点的 prev 指回 tail
  • 新节点的 next 指向 head
  • headprev 指向新节点 → 形成闭环

六、迭代器的封装与实现

6.1 普通人的写法(不封装迭代器)

cpp 复制代码
typedef list_iterator<T> iterator;

iterator begin() {
    iterator it(_head->next);
    return iterator(_head->next);
}

iterator end() {
    return _head;  // 返回哨兵节点
}

问题:直接暴露底层节点指针,缺乏封装,不符合 STL 规范。

6.2 仿 STL 的迭代器封装

cpp 复制代码
template<class T>
struct list_iterator {
    typedef list_node<T> Node;
    typedef list_iterator<T> Self;
    Node* _node;

    list_iterator(Node* node) : _node(node) {}

    // 解引用操作
    T& operator*() {
        return _node->_data;
    }

    // 前置递增
    Self& operator++() {
        _node = _node->next;
        return *this;
    }

    // 不等比较
    bool operator!=(const Self& s) {
        return _node != s._node;
    }
};

迭代器遍历图示:

复制代码
       pos
        ↓
[head] ←── 1 ←── 2 ←── 3 ←── 4
        ↑
       head
  • 使用迭代器封装底层节点指针
  • 提供 operator*operator++operator!= 等基本操作
  • 符合 STL 迭代器协议,便于与泛型算法(如 sortfind)配合使用

七、总结

本文系统梳理了 C++ STL list 容器的核心设计:

  1. 迭代器类型list 使用双向迭代器,不支持随机访问
  2. 内部结构:循环双向链表 + 哨兵节点,简化边界处理
  3. 关键操作empty_initialize 初始化哨兵,push_back 实现尾部插入
  4. 迭代器封装:通过封装节点指针,提供符合 STL 规范的迭代器接口

掌握这些原理,有助于深入理解 STL 设计思想,并为手写简易版容器打下坚实基础。


附录:参考资料

  • 《C++ Primer》第 10 章:泛型算法与容器
  • SGI STL 源码剖析
  • cppreference.comstd::list

任何的批评和建议欢迎指出,我们共同进步!

相关推荐
小陈的进阶之路1 小时前
Claude Code辅助测试:API测试与pytest自动化
android·开发语言·kotlin
denggun123451 小时前
Python两套原生信号量与swift对比
开发语言·python·swift
吴声子夜歌1 小时前
Java面试——数据结构(二)
java·数据结构·面试
kyle~1 小时前
计算机系统 --- 缓存一致性
开发语言·c++·缓存·计算机系统
栀栀栀栀栀栀1 小时前
2026/8/23 maven springboot
java·spring boot·maven
SeaDhdhdhdhdh9 小时前
MCP Server 搭建与使用指南
java·ai·agent·mcp
李妍.9 小时前
02Numpy基础(上)
开发语言·python
TheBestRucy9 小时前
Python 九阳神功之贰:面向对象(下)
开发语言·python
YH552698410 小时前
GPT‑5.6 Sol 原本支持 1M 上下文,Codex 现已放开此前限制,如何看待这次调整?
java·jvm·人工智能·gpt·算法·chatgpt