【C++指南】STL list容器完全解读(一):从入门到掌握基础操作

.
💓 博客主页:倔强的石头的CSDN主页
📝Gitee主页:倔强的石头的gitee主页
⏩ 文章专栏:《C++指南》
期待您的关注

文章目录

一、初识list容器

1.1 什么是list?

在C++标准模板库(STL)中,list是一个基于双向链表实现的序列容器。它允许在任意位置进行高效插入和删除操作,时间复杂度为O(1)。与vector不同,list不保证元素在内存中的连续存储,因此不支持随机访问。

1.2 核心特性

  • 双向链表结构:每个元素包含指向前后节点的指针
  • 动态内存分配:元素按需分配内存
  • 高效插入删除:无需移动其他元素
  • 迭代器稳定性:插入删除操作不会使已有迭代器失效(除被删除元素)

1.3 典型应用场景

  • 需要频繁在首尾之外的位置插入/删除元素
  • 元素体积较大,避免vector扩容时的拷贝开销
  • 需要维护元素的插入顺序
  • 需要合并、拆分链表等特殊操作

二、核心成员函数

2.1 默认成员函数


构造函数的重载版本

函数 功能描述 示例
默认构造函数 创建空list list<int> lst1;
填充构造函数 创建包含n个元素的list list<char> lst2(5);
拷贝构造函数 复制另一个list的内容 list<int> lst3(lst2);
移动构造函数(C++11) 转移另一个list的资源 list<int> lst4(move(lst3));
析构函数 自动释放内存(通常无需手动调用) lst1.~list();
拷贝赋值运算符 深拷贝赋值操作 lst2 = lst1;
移动赋值运算符(C++11) 高效转移资源赋值操作 lst3 = move(lst2);
cpp 复制代码
// 初始化列表构造(C++11)
list<string> fruits {"apple", "banana", "cherry"};

三、迭代器操作

3.1 基础迭代器

函数 功能 示例
begin() 返回指向第一个元素的迭代器 auto it = lst.begin();
end() 返回末尾哨兵迭代器 while(it != lst.end())
rbegin() 返回反向起始迭代器 auto rit = lst.rbegin();
rend() 返回反向结束迭代器 for(; rit != lst.rend();)

3.2 常量迭代器(C++11)

函数 功能 示例
cbegin() 返回不可修改的正向起始迭代器 auto cit = lst.cbegin();
cend() 返回不可修改的正向结束迭代器 if(cit == lst.cend())
crbegin() 返回不可修改的反向起始迭代器 auto crit = lst.crbegin();
crend() 返回不可修改的反向结束迭代器 while(crit != lst.crend())
cpp 复制代码
list<int> nums {1,2,3};
// 正向遍历
for(auto it = nums.begin(); it != nums.end(); ++it) {
    cout << *it << " ";  // 输出:1 2 3
}

四、容量与访问操作

4.1 容量查询

函数 功能 示例
size() 返回元素数量 if(lst.size() > 5)
empty() 判断容器是否为空 while(!lst.empty())

4.2 元素访问

函数 功能 示例
front() 访问首元素(可修改) lst.front() = 10;
back() 访问尾元素(可修改) cout << lst.back();
cpp 复制代码
list<double> temps {36.5, 37.1, 38.0};
temps.front() = 35.9;  // 修改首元素
cout << "当前体温:" << temps.back();  // 输出38.0

五、修改操作详解

5.1 基础修改函数

函数 功能 示例
push_front(val) 头部插入元素 lst.push_front(0);
emplace_front(args) 头部直接构造元素 lst.emplace_front("test");
pop_front() 删除头部元素 lst.pop_front();
push_back(val) 尾部插入元素 lst.push_back(100);
emplace_back(args) 尾部直接构造元素 lst.emplace_back(1,2);
pop_back() 删除尾部元素 lst.pop_back();
clear() 清空所有元素 lst.clear();

push_back vs emplace_back

cpp 复制代码
class Student {
public:
    Student(int id, string name) : id(id), name(name) {}
private:
    int id;
    string name;
};

list<Student> roster;
roster.push_back(Student(101, "Alice"));  // 构造临时对象+拷贝
roster.emplace_back(102, "Bob");         // 直接构造(高效)

5.2 高级修改操作

函数 功能 示例
assign(n, val) 用n个val替换内容 lst.assign(5, 0);
assign(beg, end) 用迭代器范围替换内容 lst.assign(vec.begin(), vec.end());
swap(other) 交换两个list的内容 lst1.swap(lst2);
resize(n) 调整元素数量 lst.resize(10);
resize(n, val) 调整数量并用val填充新增元素 lst.resize(15, -1);
cpp 复制代码
list<int> nums;
nums.assign({1,2,3});       // 内容变为[1,2,3]
nums.resize(5);             // 变为[1,2,3,0,0]
nums.resize(3);             // 截断为[1,2,3]

5.3 插入与删除

insert重载版本
cpp 复制代码
iterator insert(iterator pos, const T& val);  // 单元素插入
void insert(iterator pos, size_t n, const T& val); // 批量插入
void insert(iterator pos, InputIt first, InputIt last); // 范围插入
erase操作
cpp 复制代码
iterator erase(iterator pos);                 // 删除单个元素
iterator erase(iterator first, iterator last); // 删除区间元素

示例

cpp 复制代码
list<int> data {10,20,30};
auto it = data.begin();
advance(it, 1);

data.insert(it, 15);        // [10,15,20,30]
data.insert(it, 2, 18);     // [10,15,18,18,20,30]
vector<int> tmp {25,35};
data.insert(data.end(), tmp.begin(), tmp.end()); // 末尾追加

data.erase(it);             // 删除第二个18

六、特殊成员函数

6.1 条件操作

函数 功能 示例
remove(val) 删除所有等于val的元素 lst.remove(5);
remove_if(pred) 删除满足条件的元素 lst.remove_if([](int n){ return n%2==0; });
cpp 复制代码
list<int> nums {1,2,3,2,5};
nums.remove(2);  // 删除所有2 → [1,3,5]
nums.remove_if([](int x){ return x>3; }); // → [1,3]

6.2 链表特有操作

函数 功能 示例
unique() 删除连续重复元素 lst.unique();
merge(other) 合并有序链表 lst1.merge(lst2);
sort() 排序元素(升序) lst.sort();
splice(pos, other) 转移另一个链表的元素 lst1.splice(it, lst2);
cpp 复制代码
list<int> a {1,3,5}, b {2,4,6};
a.merge(b);       // a变为[1,2,3,4,5,6], b为空
a.sort();         // 排序(若未有序)

list<int> x {10,20}, y {30,40};
auto pos = x.begin();
x.splice(pos, y); // x变为[30,40,10,20], y为空

七、总结与进阶

本文详细介绍了C++ list容器的基本特性和使用方法。通过大量的代码示例,我们学习了如何正确使用list进行元素的增删改查操作。list作为STL中重要的序列式容器,其独特的链表结构使其在特定场景下具有不可替代的优势。

在接下来的系列文章中,我们将深入探讨:

  • list的高级应用技巧
  • list在实际项目中的最佳实践案例

下篇预告《【C++指南】C++ list容器完全解读(二):list模拟实现,底层架构揭秘》,我们将通过剖析STL源码实现,带你理解list的底层工作机制

相关推荐
DonciSacer3 分钟前
第一章-Rust入门
开发语言·后端·rust
我是一只鱼02234 分钟前
LeetCode算法题 (移除链表元素)Day15!!!C/C++
c++·算法·leetcode·链表
Lenyiin17 分钟前
《 C++ 点滴漫谈: 三十六 》lambda表达式
c++
西京刀客19 分钟前
golang常用库之-标准库text/template
开发语言·后端·golang
落榜程序员31 分钟前
浅拷贝和深拷贝的区别
java·开发语言
ATaylorSu34 分钟前
C++ -- 实现日期类
c++·学习
renhl2521 小时前
C++11新特性_委托构造函数
java·前端·c++
purrrew1 小时前
【Java ee初阶】多线程(7)
java·开发语言
?!7141 小时前
数据结构之哈夫曼树
c语言·数据结构·c++·算法
元亓亓亓1 小时前
Java后端开发day39--方法引用
java·开发语言