C++初阶(十五)--STL--list 的深度解析与全面应用

文章目录

一、头文件与基本概念

二、构造函数和析构函数

1.构造函数

2.析构函数

三、元素访问

front

back

四、迭代器相关函数

begin

end

rebegin(反向迭代器)

rend(反向迭代器)

五、容量相关函数

empty

size

max_size

六、修改器

assign

push_front

push_back

pop_front

pop_back

insert

erase

swap

clear

resize

七、操作

merge

splice

remove

remove_if

reserve

sort

unique

emplace函数(C++11及以上)

八、非成员函数重载

1.比较运算符重载(==、!=、<、<=、>、>=)

[2.swap 函数(非成员函数重载)](#2.swap 函数(非成员函数重载))


C++ 的标准模板库(STL)中的 list 是一个功能强大且灵活的双向链表容器,它提供了众多接口函数来满足各种编程需求。在本篇博客中,我们将深入探讨 list 的所有成员函数,包括一些相对不太常用但在特定场景下非常有用的函数,我们这里只探讨基本的使用,不探讨底层原理,下一篇博客,我们将会模拟实现list。

一、头文件与基本概念

要使用list容器,首先需要包含<list>头文件,并引入std命名空间,使得我们可以直接使用list而不是std::list。

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;

list 作为双向链表容器,其每个节点包含数据以及指向前一个节点和后一个节点的指针,这使得它在插入和删除操作上具有独特的优势,但在随机访问方面相对较弱。

二、构造函数和析构函数

1.构造函数

默认构造函数:创建一个空的list容器

cpp 复制代码
list<int> myList1;

填充构造函数:构造一个含有n个val的某类型容器。

cpp 复制代码
	list<int> myList2(10, 2);

初始化列表构造函数:使用给定的初始化列表来初始化list

cpp 复制代码
list<int> myList3 = { 1, 2, 3, 4, 5 };

拷贝构造函数:用另一个同类型的 list 容器来初始化新的 list

cpp 复制代码
list<int> myList4(myList1);

范围构造函数:依据其他容器(如数组、vector 等)中指定范围的元素构建 list。例如,假设有数组 int arr[] = {6, 7, 8, 9, 10};

cpp 复制代码
list<int> myList4(arr, arr + 5);

移动构造函数(C++11及以上):允许将一个临时 list 资源转移到新创建的 list 中,以提高性能。例如:

cpp 复制代码
list<int> createTempList()
{
	list<int> temp = { 11, 12, 13 };
	return temp;
}

list<int> myList6 = createTempList();  // 使用移动构造函数初始化 myList6

2.析构函数

list 容器对象超出作用域或被显式删除时,析构函数会自动被调用,释放链表中每个节点所占用的内存资源,确保内存不会泄漏。

三、元素访问

front

作用:返回list容器中的第一个元素

cpp 复制代码
cout << "第一个元素: " << myList2.front() << endl;

back

作用:返回list容器中的最后一个元素

cpp 复制代码
cout << "最后一个元素: " << myList2.back() << endl;

四、迭代器相关函数

begin

返回指向list容器中第一个元素的正向迭代器,通过这个迭代器可以顺序遍历容器中的元素

cpp 复制代码
list<int>::iterator itBegin = myList2.begin();

end

返回指向list容器中最后一个元素之后位置的正向迭代器,用于标记整形遍历的结束。

cpp 复制代码
list<int>::iterator itEnd = myList2.end();

rebegin(反向迭代器)

返回指向list容器中最后一个元素的反向迭代器,可用于从后向前遍历容器

cpp 复制代码
list<int>::reverse_iterator itRBegin = myList2.rbegin();

rend(反向迭代器)

返回指向list容器中第一个元素之前位置的反向迭代器,标记反向遍历的结束。

cpp 复制代码
list<int>::reverse_iterator itREnd = myList2.rend();

五、容量相关函数

empty

检查list容器是否为空,为空时返回true,否则返回false。

cpp 复制代码
if (myList1.empty()) {
    cout << "myList1 为空" << endl;
} else {
    cout << "myList1 不为空" << endl;
}

size

返回list容器中当前元素的数量。

cpp 复制代码
cout << "myList2 的元素个数: " << myList2.size() << endl;

max_size

返回list容器理论上能够容纳的最大元素数量,这个数量通常取决于系统资源和实现细节。

cpp 复制代码
cout << "myList2 最大可容纳元素数: " << myList2.max_size() << endl;

六、修改器

assign

使用新的元素替换list容器中的所有现有元素。

cpp 复制代码
myList2.assign(3, 100);  // 将 myList2 中的元素替换为 3 个 100

也可以使用一个范围的元素来进行替换,假设存在另一个list: list<int> otherList = {200,300,400};

cpp 复制代码
list<int> otherList = { 200,300,400 };
myList1.assign(otherList.begin(), otherList.end());

push_front

在list容器的头部插入一个新元素。

cpp 复制代码
myList2.push_front(0);

push_back

在list容器的尾部插入一个新元素。

cpp 复制代码
myList.push_back(6);

pop_front

移除 list 容器头部的元素。

cpp 复制代码
myList2.pop_front();

pop_back

移除 list 容器尾部的元素

cpp 复制代码
myList2.pop_back();

insert

在指定位置插入一个元素,列如,在myList2的第二个位置插入值为15的元素。

cpp 复制代码
auto itInsertPos = myList2.begin();
++itInsertPos;
myList2.insert(itInsertPos, 15);

也可以一次性插入多个相同元素,如在myList的开头插入3个值为5的元素:

cpp 复制代码
myList2.insert(myList2.begin(), 3, 5);

也可以插入一个范围的元素,假设有 vector<int> vec = {7,8,9}。

cpp 复制代码
myList2.insert(myList2.end(), vec.begin(), vec.end());

erase

移除指定位置的元素。列如,移除myList2中的第三个元素。

cpp 复制代码
auto itErasePos = myList2.begin();
++itErasePos;
++itErasePos;
myList2.erase(itErasePos);

也可以移除一个范围的元素,如移除myList2中的第二个元素到第四个元素(不包括第四个)。

cpp 复制代码
auto start = myList2.begin();
++start;
auto end = start;
++end;
++end;
myList2.erase(start, end);

swap

交换两个 list容器的内容

cpp 复制代码
list<int> listA = {1, 2, 3};
list<int> listB = {4, 5, 6};
listA.swap(listB);

clear

移除list容器中的所有元素,使其变为空容器

cpp 复制代码
myList2.clear();

resize

两种情况:

  1. 当所给值大于当前的size时,将size扩大到该值,扩大的数据为第二个所给值,若未给出,则默认为容器所存储类型的默认构造函数所构造出来的值。
  2. 当所给值小于当前的size时,将size缩小到该值。
cpp 复制代码
myList1.resize(10);  // 将 myList1 大小调整为 10,新增元素使用默认值初始化

myList1.resize(5);  // 将 myList1 大小调整为 5,移除后面的元素

myList1.resize(8, 20);  // 将 myList1 大小调整为 8,新增元素值为 20

七、操作

merge

将另一个已排序的 list 合并到当前 list 中,合并后当前 list 仍保持有序。假设 list<int> listC = {1, 3, 5};list<int> listD = {2, 4, 6};,且 listClistD 都已排序。

cpp 复制代码
listC.merge(listD);

splice

将另一个list中的一个或多个元素移动到当前list的指定位置,列如,将 listD 的所有元素移动到 listC 的开头。

cpp 复制代码
listC.splice(listC.begin(), listD);

也可以移动指定位置的单个元素,假设有 list<int> listE = {10,20,30}。

cpp 复制代码
auto itE = listE.begin();
++itE;
listC.splice(listC.begin(), listE, itE);

remove

移除list容器中所有与指定值相等的元素

cpp 复制代码
myList2.remove(2);

remove_if

根据指定的谓词(函数或函数对象)移除满足条件的元素。例如,移除所有偶数元素。

cpp 复制代码
list<int> listG = { 1, 2, 3, 4, 5, 6 };
listG.remove_if([](int x) { return x % 2 == 0; });//去除偶数

reserve

反转list容器中元素的顺序

cpp 复制代码
list<int> listH = {1, 2, 3, 4, 5};
listH.reverse();

sort

list 容器中的元素进行排序。默认按照升序排序,如果需要自定义排序规则,可以传入比较函数或函数对象。例如,按照降序排序,需要按照以下代码写。

cpp 复制代码
list<int> listI = {5, 3, 4, 1, 2};
listI.sort(greater<int>());

unique

移除list容器中连续的重复元素,只保留一个。

cpp 复制代码
list<int> listJ = {1, 1, 2, 2, 3, 3, 3, 4, 4};
listJ.unique();

emplace函数(C++11及以上)

在指定位置原地构造一个新元素,相比于 insert 函数,emplace 函数可以避免不必要的临时对象创建和复制,提高效率。例如,在 list 开头插入一个值为 100 的元素:

cpp 复制代码
myList2.emplace(myList2.begin(), 100);

八、非成员函数重载

1.比较运算符重载**(==!=<<=>>=)**

可以直接比较两个 list 容器是否相等或确定它们的大小关系,比较基于元素的逐对比较。例如:

cpp 复制代码
list<int> listK = {1, 2, 3};
list<int> listL = {1, 2, 3};
if (listK == listL) {
    cout << "listK 和 listL 相等" << endl;
}

2.swap 函数(非成员函数重载)

提供了一种更方便的方式来交换两个 list 容器的内容,与成员函数 swap 功能相同,但调用方式略有不同。

cpp 复制代码
list<int> listM = {4, 5, 6};
list<int> listN = {7, 8, 9};
swap(listM, listN);

本篇博客到此结束,欢迎评论区留言~


本篇博客参考资料网址:cplusplus.com

相关推荐
姜姜姜姜名字都有2 分钟前
青训10_1121_01_游戏排名第三大的分数
开发语言·python
new Vue()5 分钟前
ES6中Promise的使用场景
开发语言·前端·javascript
lix的小鱼11 分钟前
Scala之Array数组
java·开发语言·后端·python·scala
喻师傅12 分钟前
Scala—数组(数组定义、数组常用方法等)— 用法详解
开发语言·scala
45W冲冲冲15 分钟前
WIN10+CMAKE+MinGW+Opencv/C++ 和VScode开发环境搭建
c++·vscode·opencv
anqi2717 分钟前
Scala 的Array 和 ArrayBuffer 集合
开发语言·后端·scala
春蕾夏荷_72829772519 分钟前
MFC 对话框中显示CScrollView实例
c++·mfc·cscrollview
柔弱女子爱java25 分钟前
XML文件(超详细):XML文件概念、作用、写法、如何用程序解析XML、写入XML、dom4j框架、DTD文档、schema文档
xml·java·开发语言·后端
mingyuewanfeng1 小时前
R语言4.3.0安装教程【附安装包】
开发语言·r语言
江-小北2 小时前
Java基础面试题05:简述快速失败(fail-fast)和安全失败(fail-safe)的区别 ?
java·开发语言·python