C++学习笔记(list)3.6

一、list基础介绍与使用

list是STL中的序列式容器,底层为带头结点的双向 循环链表,其接口丰富,核心需掌握基础使用方法,再深入底层原理以实现扩展。

1.1 list的构造

提供四种核心构造函数,满足不同初始化需求:

|-----------------------------------------------------------|-----------------------------|
| 构造函数 | 接口说明 |
| list (size_type n, const value_type& val = value_type()) | 构造包含n个值为val的元素的list |
| list() | 构造空的list |
| list (const list& x) | 拷贝构造函数,用已有list初始化新list |
| list (InputIterator first, InputIterator last) | 用[first, last)区间内的元素构造list |

1.2 list迭代器的使用

迭代器可暂理解为指向list节点的指针,分正向和反向两类,核心是掌握其移动规则:

|---------------|----------------------------------------|
| 函数声明 | 接口说明 |
| begin + end | begin返回首元素迭代器,end返回尾元素下一个位置迭代器(正向) |
| rbegin + rend | rbegin对应end位置,rend对应begin位置(反向) |

关键注意

  1. 正向迭代器(begin/end):++操作,迭代器向后移动;

  2. 反向迭代器(rbegin/rend):++操作,迭代器向前移动。

1.3 list容量操作

仅提供两个核心容量查询接口,简单易用:

|-------|----------------------------|
| 函数声明 | 接口说明 |
| empty | 检测list是否为空,空返回true,否则false |
| size | 返回list中有效节点的个数 |

1.4 list元素访问

仅支持首尾元素的直接访问,不支持随机访问(底层链表特性):

|-------|---------------|
| 函数声明 | 接口说明 |
| front | 返回首节点值的引用 |
| back | 返回尾节点值的引用 |

1.5 list修改操作(modifiers)

提供增删、插入、交换、清空等核心修改接口,是list使用的重点:

|------------|-----------------------|
| 函数声明 | 接口说明 |
| push_front | 首元素前插入值为val的元素 |
| pop_front | 删除第一个元素 |
| push_back | 尾部插入值为val的元素 |
| pop_back | 删除最后一个元素 |
| insert | 在position位置插入值为val的元素 |
| erase | 删除position位置的元素 |
| swap | 交换两个list中的所有元素 |
| clear | 清空list中的所有有效元素 |

1.6 list迭代器失效

核心结论 :插入操作不会导致迭代器失效,仅删除操作 会让指向被删除节点的迭代器失效,其他迭代器不受影响(链表节点独立,删除仅影响当前节点)。

错误与正确示例
  • 错误:erase后直接++失效的迭代器,迭代器指向已释放节点

    cpp 复制代码
    auto it = l.begin();
    while (it != l.end()) {
        l.erase(it); 
        ++it; // 错误:it已失效
    }
  • 正确:利用后置++,先传参再移动迭代器;或接收erase返回值

    cpp 复制代码
    auto it = l.begin();
    while (it != l.end()) {
        l.erase(it++); // 推荐
        // 等价:it = l.erase(it);
    }

二、list的模拟实现

模拟实现的核心是掌握底层双向循环链表结构,以及接口的逻辑实现,重点为反向 迭代器 的实现

2.1 基础模拟实现

需先熟悉list底层带头结点的双向循环链表结构,再按接口功能依次实现构造、迭代器、增删查改、容量查询等接口,核心是保证链表节点的双向指向和循环特性。

2.2 反向迭代器的模拟实现

反向迭代器的核心逻辑:反向迭代器的++ = 正向迭代器的--,反向迭代器的-- = 正向迭代器的++ ,因此可借助正向迭代器做包装实现,无需重新编写底层逻辑。

核心实现要点
  1. 反向迭代器类模板接收正向迭代器作为模板参数,内部封装一个正向迭代器成员;

  2. 使用typename明确迭代器的关联类型(Ref/Ptr),避免编译器解析歧义;

  3. 重载*/->实现元素访问,重载++/--实现迭代器移动,重载==/!=实现迭代器比较;

  4. 解引用*时,需先将正向迭代器向前移动一位,再返回值(匹配反向迭代器的遍历逻辑)。

核心代码框架
cpp 复制代码
template<class Iterator>
class ReverseListIterator {
public:
    typedef typename Iterator::Ref Ref;
    typedef typename Iterator::Ptr Ptr;
    typedef ReverseListIterator<Iterator> Self;

    ReverseListIterator(Iterator it): _it(it){}
    // 元素访问
    Ref operator*(){
        Iterator temp(_it);
        --temp;
        return *temp;
    }
    Ptr operator->(){ return &(operator*());}
    // 迭代器移动
    Self& operator++(){--_it; return *this;}
    Self operator++(int){Self temp(*this); --_it; return temp;}
    Self& operator--(){++_it; return *this;}
    Self operator--(int){Self temp(*this); ++_it; return temp;}
    // 迭代器比较
    bool operator!=(const Self& l)const {return _it != l._it;}
    bool operator==(const Self& l)const {return _it == l._it;}

private:
    Iterator _it; // 封装正向迭代器
};

三、list与vector的对比

vector和list是STL核心序列式容器,底层结构的差异导致二者特性、效率、应用场景截然不同,是学习的重点区分点。

|--------|----------------------------------------------|-----------------------------|
| 对比维度 | vector | list |
| 底层结构 | 动态顺序表,一段连续的内存空间 | 带头结点的双向循环链表 |
| 随机访问 | 支持,访问元素效率O(1) | 不支持,访问元素效率O(N) |
| 插入/删除 | 任意位置效率低,需搬移元素(O(N));插入可能增容(开辟新空间+拷贝+释旧),效率更低 | 任意位置效率高,无需搬移元素(O(1)) |
| 空间利用率 | 连续空间,无内存碎片,空间/缓存利用率高 | 节点动态开辟,小节点易造成内存碎片,空间/缓存利用率低 |
| 迭代器本质 | 原生态指针 | 对节点指针的封装 |
| 迭代器失效 | 插入:所有迭代器失效(可能增容);删除:当前迭代器失效,需重新赋值 | 插入:无迭代器失效;删除:仅指向被删节点的迭代器失效 |
| 核心应用场景 | 需高效存储、支持随机访问,对插入/删除效率要求低 | 存在大量插入/删除操作,对随机访问无要求 |

四、核心学习总结

  1. list的底层特性决定其核心优势是任意位置的插入/删除效率高 ,劣势是不支持 随机访问,需与vector做好场景区分;

  2. 迭代器是list使用的关键,需牢记正向/反向迭代器的移动规则迭代器失效的场景及解决方法

  3. 模拟实现的重点是反向迭代器的包装思想,借助正向迭代器实现反向迭代器,体现代码的复用性;

  4. 实际开发中,根据需求选择容器:需随机访问用vector,需大量增删用list。

相关推荐
星幻元宇VR2 小时前
VR生产安全学习机|开启智慧安全培训新时代
人工智能·科技·学习·安全·vr
X在敲AI代码2 小时前
D32次 第2题 因子化简
开发语言·c++
deng-c-f2 小时前
Linux C/C++ 学习日记(80):Kafka(八):topic会自动创建吗?
linux·c++·学习·karfka
Don.TIk2 小时前
深度学习学习笔记
笔记·深度学习·学习
知识分享小能手2 小时前
PostgreSQL 入门学习教程,从入门到精通,PostgreSQL 16 数据备份与还原详解 —语法、案例与实战(16)
数据库·学习·postgresql
星幻元宇VR2 小时前
VR科普学习一体机,在学校教育的应用前景
科技·学习·安全·vr·虚拟现实
猫吻鱼2 小时前
【笔记02】【Reactor 响应式编程】
笔记
灰色小旋风2 小时前
力扣第九题C++回文数
c++·算法·leetcode
庭前云落2 小时前
从零开始的OpenZeppelin学习 1| 安装、使用
学习·区块链