【C++】list的使用(上)

🔥个人主页: Forcible Bug Maker
🔥专栏: STL || C++
目录
- 前言
- 🌈关于list
- 🔥默认成员函数
- ==构造函数(constructor)==
- ==析构函数(destructor)==
- ==赋值运算符重载==
- 🔥迭代器接口(Iterators)
- 🔥容量获取接口(Capacity)
- ==empty和size==
- 🔥元素获取(Element access)
- 🔥修改器(Modifiers)
- ==assign==
- ==push_back,pop_back,push_front和pop_front==
- ==insert==
- ==erase==
- ==resize==
- ==clear==
- 结语
前言
本篇博客主要内容:STL库中list的介绍以及list用法的讲解。
我们已经知道,string和vector的底层都是简单的顺序表,而list的底层就和之前的两个大不相同了,list的底层是一个带头双向循环链表。学习list之前,如果你还不知道什么是链表,完全由必要学习一下,可以看看我初阶数据结构所讲到的内容:初阶数据结构-顺序表和链表(C语言)
在C++中,我们可以直接使用list创建链表。
🌈关于list

list是可以在常数范围内任意位置进行插入和删除的序列式容器,并且可以前后双向迭代。
list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针向其前一个元素和后一个元素。
list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已经让其更简单更高效。
与其他序列式容器相比(array,vector,deque),list通常在任意位置进行插入,移除元素的执行效率更好。
于其他序列式容器相比,list和forward_list最大的缺陷是不支持元素的随机访问,比如:需要访问list的第六个元素,必须从已有的位置(比如头部或尾部)迭代到该位置,这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个结点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)。
🔥默认成员函数

构造函数(constructor)

注:对于最后一个参数(alloc),可以不用深究,在后期学了内存池相关的内容后会细讲。
构造一个list容器对象,可以根据以下四种方式初始化:
default (1)
explicit list (const allocator_type& alloc = allocator_type());
这是std::list的无参构造。它创建了一个不含任何元素的空list对象。其中explicit关键字阻止了隐式类型转换。
fill (2)
explicit list (size_type n, const value_type& val = value_type(),const allocator_type& alloc = allocator_type());
构造一个含有n个val值得list对象。
range (3)
template <class InputIterator>list (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type());
按迭代器区间[first, last) 的内容顺序构造list对象。
copy (4)
list (const list& x);
构造一个x对象得拷贝。
允许隐式类型转换。
代码案例:
// constructing lists
#include <iostream>
#include <list>int main()
{// constructors used in the same order as described above:std::list<int> first; // 构建数据类型为整型的一个空链表std::list<int> second(4, 100); // 构建一个包含四个值为100的链表std::list<int> third(second.begin(), second.end()); // 通过second链表的迭代器构建thirdstd::list<int> fourth(third); // 用third拷贝一个相同的链表fourth// the iterator constructor can also be used to construct from arrays:int myints[] = { 16,2,77,29 };std::list<int> fifth(myints, myints + sizeof(myints) / sizeof(int));std::cout << "The contents of fifth are: ";for (std::list<int>::iterator it = fifth.begin(); it != fifth.end(); it++)std::cout << *it << ' ';std::cout << '\n';return 0;
}

析构函数(destructor)

析构函数是当编译器出了对象的生命周期时自动调用的默认成员函数,释放开辟的内存空间。
赋值运算符重载

通过已有对象给被操作对象分配新的值,覆盖它原来的内容,并根据内容调整size的大小。
list& operator= (const list& x);
从x中拷贝所有的内容到被操作list对象中。
在调用之前容器中持有的任何元素都将被分配给新值或被销毁。
代码案例:
// assignment operator with lists
#include <iostream>
#include <list>int main()
{std::list<int> first(3); // list of 3 zero-initialized intsstd::list<int> second(5); // list of 5 zero-initialized intssecond = first;first = std::list<int>();std::cout << "Size of first: " << int(first.size()) << '\n';std::cout << "Size of second: " << int(second.size()) << '\n';return 0;
}
两个包含整型元素的列表容器都被初始化为不同大小的序列。然后,second容器被first容器赋值,所以现在两个容器相等并且大小都是3。接着,first容器被赋值给一个新构造的空容器对象(匿名对象),因此它的大小最终变为0。

🔥迭代器接口(Iterators)

对于STL的各种容器,迭代器的规则都是极其相似的。
和vector和string相同,begin获取指向list对象首元素的迭代器,end指向链表尾元素下一位的迭代器。
我认为迭代器在vector和string的基础上可以直接上代码了,大家能直接了解其用法。
代码案例:
#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt({ 1,2,3,4 });// 获取正向迭代器遍历list<int>::iterator it = lt.begin();while (it != lt.end()) {cout << *it << " ";++it;}cout << endl;// 获取反向迭代器遍历list<int>::reverse_iterator rit = lt.rbegin();while (rit != lt.rend()) {cout << *rit << " ";++rit;}cout << endl;return 0;
}

不过在使用list迭代器需要特别注意的一点:list链表的迭代器不支持加减运算,只支持++和- -运算符,如it += 1或it = it + 3的写法会使编译器报错。
🔥容量获取接口(Capacity)

empty和size
bool empty() const;
判断list对象是否为空。
size_type size() const;
获取list对象元素个数。
代码案例:
#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt1;list<int> lt2({ 1,2,3,4 });cout << "lt1.empty():" << lt1.empty() << endl;cout << "lt2.empty():" << lt2.empty() << endl;cout << endl;cout << "lt1.size():" << lt1.size() << endl;cout << "lt2.size():" << lt2.size() << endl;return 0;
}

🔥元素获取(Element access)

reference front();
const_reference front() const;
获取list对象首元素。
reference back();
const_reference back() const;
获取list对象尾元素。
代码案例:
#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt({ 1,2,3,4 });cout << lt.front() << endl;cout << lt.back() << endl;return 0;
}

🔥修改器(Modifiers)

assign

range (1)
template <class InputIterator>void assign (InputIterator first, InputIterator last);
fill (2)
void assign (size_type n, const value_type& val);
两个重载都可以给list对象分配新内容,将对象原有的内容覆盖。
代码案例:
#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt1({ 1,2,3,4 });list<int> lt2({ 0,0,0,0 });lt1.assign(lt2.begin(), lt2.end());for (auto e : lt1) {cout << e << " ";}cout << endl;lt1.assign(8, -1);for (auto e : lt1) {cout << e << " ";}return 0;
}

push_back,pop_back,push_front和pop_front
分别对应着链表的尾插尾删和头插头删。
代码案例:
#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt({ 0,0,0 });for (auto e : lt) {cout << e << " ";}cout << endl;lt.push_back(-1);for (auto e : lt) { cout << e << " "; }cout << endl;lt.pop_back();for (auto e : lt) { cout << e << " "; }cout << endl;lt.push_front(-1);for (auto e : lt) { cout << e << " "; }cout << endl;lt.pop_front();for (auto e : lt) { cout << e << " "; }cout << endl;return 0;
}

insert

single element (1)
iterator insert (iterator position, const value_type& val);
在迭代器指向元素之前插入val。
fill (2)
void insert (iterator position, size_type n, const value_type& val);
在迭代器指向元素之前插入n个val。
range (3)
template <class InputIterator>void insert (iterator position, InputIterator first, InputIterator last);
在迭代器指向元素之前按顺序插入迭代器区间[first, last)内的值。
带吗案例:
#include <iostream>
#include <list>
#include <vector>int main()
{std::list<int> mylist;std::list<int>::iterator it;// set some initial values:for (int i = 1; i <= 5; ++i) mylist.push_back(i); // 1 2 3 4 5it = mylist.begin();++it; // it points now to number 2 ^mylist.insert(it, 10); // 1 10 2 3 4 5// "it" still points to number 2 ^mylist.insert(it, 2, 20); // 1 10 20 20 2 3 4 5--it; // it points now to the second 20 ^std::vector<int> myvector(2, 30);mylist.insert(it, myvector.begin(), myvector.end());// 1 10 20 30 30 20 2 3 4 5// ^std::cout << "mylist contains:";for (it = mylist.begin(); it != mylist.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

erase

iterator erase (iterator position);
iterator erase (iterator first, iterator last);
删除list容器中一个迭代器(position)指向的元素或者一段迭代器区间(first, last]内的元素。
返回值为指向被删除元素下一元素的迭代器。
代码案例:
#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt({ 1,2,3,4,5 });for (auto e : lt) { cout << e << " "; }cout << endl;list<int>::iterator it = lt.begin();++it;it = lt.erase(it);for (auto e : lt) { cout << e << " "; }cout << endl;it = lt.erase(it, lt.end());for (auto e : lt) { cout << e << " "; }cout << endl;return 0;
}

resize
void resize (size_type n, value_type val = value_type());
此接口函数用于调整容器的大小,使其包含n个元素。
如果n小于当前容器的大小,内容将被缩减为其前n个元素,移除超出n的部分(并销毁它们)。
如果n大于当前容器的大小,内容将通过在末尾插入所需数量的新元素来扩展,以达到大小为n。如果指定了val,新元素将被初始化为val的副本;否则,它们将进行默认值初始化。
// resizing list
#include <iostream>
#include <list>int main()
{std::list<int> mylist;// set some initial content:for (int i = 1; i < 10; ++i) mylist.push_back(i);mylist.resize(5);mylist.resize(8, 100);mylist.resize(12);std::cout << "mylist contains:";for (std::list<int>::iterator it = mylist.begin(); it != mylist.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

clear
void clear();
从列表容器(其中的元素将被销毁)中移除所有元素,使size的大小变为0。
结语
本篇博客给大家初步介绍了list,其底层是一个双向循环链表,讲解了list的一些函数接口,如修改器,元素访问,以及迭代器接口的使用方式。这些功能和规则和vector,string的接口大同小异,名称也大都一致,降低了我们的学习成本。
博主后续还会产出更多有关于STL的内容,感谢大家的支持。♥
相关文章:
【C++】list的使用(上)
🔥个人主页: Forcible Bug Maker 🔥专栏: STL || C 目录 前言🌈关于list🔥默认成员函数构造函数(constructor)析构函数(destructor)赋值运算符重载 …...
【代码随想录训练营】【Day 37】【贪心-4】| Leetcode 840, 406, 452
【代码随想录训练营】【Day 37】【贪心-4】| Leetcode 840, 406, 452 需强化知识点 python list sort的高阶用法,两个key,另一种逆序写法python list insert的用法 题目 860. 柠檬水找零 思路:注意 20 块找零,可以找3张5块升…...
concat是什么?前端开发者必须掌握的数组拼接利器
concat是什么?前端开发者必须掌握的数组拼接利器 在前端开发中,concat是一个极其重要的概念,它能够帮助我们实现数组之间的无缝拼接。那么,concat到底是什么?为什么它在前端开发中如此重要?接下来…...
WHAT - 容器化系列(一)
这里写目录标题 一、什么是容器与虚拟机1.1 什么是容器1.2 容器的特点1.3 容器和虚拟机的区别虚拟机(VM):基于硬件的资源隔离技术容器:基于操作系统的资源隔离技术对比总结应用场景 二、容器的实现原理1. Namespace(命…...
QT7_视频知识点笔记_67_项目练习(页面以及对话框的切换,自定义数据类型,DB数据库类的自定义及使用)
视频项目:7----汽车销售管理系统(登录,品牌车管理,新车入库,销售统计图表)-----项目视频没有,代码也不全,更改项目练习:学生信息管理系统。 学生信息管理系统࿱…...
windows10系统64位安装delphiXE11.2完整教程
windows10系统64位安装delphiXE11.2完整教程 https://altd.embarcadero.com/download/radstudio/11.0/radstudio_11_106491a.iso XE11.1 https://altd.embarcadero.com/download/radstudio/11.0/RADStudio_11_2_10937a.iso XE11.2 关键使用文件在以下内容:windows10…...
09.责任链模式
09. 责任链模式 什么是责任链设计模式? 责任链设计模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许将请求沿着处理者对象组成的链进行传递,直到有一个处理者对象能够处理该请求为止。这种模式的目的…...
Amazon云计算AWS(一)
目录 一、基础存储架构Dynamo(一)Dynamo概况(二)Dynamo架构的主要技术 二、弹性计算云EC2(一)EC2的基本架构(二)EC2的关键技术(三)EC2的安全及容错机制 提供的…...
十_信号4-SIGCHLD信号
SIGCHLD信号 在学习进程控制的时候,使用wait和waitpid系统调用何以回收僵尸进程,父进程可以阻塞等待,也可以非阻塞等待,采用轮询的方式不停查询子进程是否退出。 采用阻塞式等待,父进程就被阻塞了,什么都干…...
HCIP的学习(27)
RSTP—802.1W—快速生成树协议 STP缺陷: 1、收敛速度慢----STP的算法是一种被动的算法,依赖于计时器来进行状态变化 2、链路利用率低 RSTP向下兼容STP协议。(STP不兼容RSTP) 改进点1—端口角色 802.1D协议---根端口、指定端口…...
6. MySQL 查询、去重、别名
文章目录 【 1. 数据表查询 SELECT 】1.1 查询表中所有字段使用 * 查询表的所有字段列出表的所有字段 1.2 查询表中指定的字段 【 2. 去重 DISTINCT 】【 3. 设置别名 AS 】3.1 为表指定别名3.2 为字段指定别名 【 5. 限制查询结果的条数 LIMIT 】5.1 指定初始位置5.2 不指定初…...
Oracle导出clob字段到csv
使用UTL_FILE ref: How to Export The Table with a CLOB Column Into a CSV File using UTL_FILE ?(Doc ID 1967617.1) --preapre data CREATE TABLE TESTCLOB(ID NUMBER, MYCLOB1 CLOB, MYCLOB2 CLOB ); INSERT INTO TESTCLOB(ID,MYCLOB1,MYCLOB2) VALUES(1,Sample row 11…...
C++无锁(lock free)队列moodycamel::ConcurrentQueue
moodycamel::ConcurrentQueue介绍 moodycamel::ConcurrentQueue一个用C++11实现的多生产者、多消费者无锁队列。 它具有以下特点: 1.快的让人大吃一惊,详见不同无锁队列之间的压测对比 2.单头文件实现,很容易集成到你的项目中 3.完全线程安全的无锁队列,支持任意线程数的并…...
python办公自动化——(二)替换PPT文档中图形数据-柱图
效果: 数据替换前 : 替换数据后: 实现代码 import collections.abc from pptx import Presentation from pptx.util import Cm,Pt import pyodbc import pandas as pd from pptx.chart.data impo…...
vue不同页面切换的方式(Vue动态组件)
v-if实现 <!--Calender.vue--> <template><a-calendar v-model:value"value" panelChange"onPanelChange" /></template> <script setup> import { ref } from vue; const value ref(); const onPanelChange (value, mod…...
Linux下Qt Creator无法输入中文(已解决)
1. 首先确保安装了搜狗输入法,且能正常运行。 2.克隆源码到本地。 git clone https://gitcode.com/fcitx/fcitx-qt5.git 3.检查Qt Creator版本,如下图所示,为基于Qt6的。 4. 进入源码目录,建立build文件夹,修改CMak…...
Codeforces 提交Java代码(自己处理输入输出)
示例一(A. Watermelon) 题目地址 Problem - 4A - Codeforces 题目截图 提交方式 可以提交本地文件,也可以在线提交。我们这里选择在线提交方式,点击上图中的 SUBMIT 按钮,会进入如下界面。 输入Java代码效果如下&a…...
剖析vue中nextTick源码
代码逻辑梳理: callbacks 数组用于存储待执行的回调函数,waiting 变量用于标记是否有待执行的回调函数。 flushCallbacks 函数用于执行所有存储在 callbacks 数组中的回调函数,并在执行完成后将 waiting 设置为 false。 timer 函数根据环境…...
SSM牙科诊所管理系统-计算机毕业设计源码98077
目 录 摘要 1 绪论 1.1研究目的与意义 1.2国内外研究现状 1.3ssm框架介绍 1.4论文结构与章节安排 2 牙科诊所管理系统系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能…...
【C++进阶】深入STL之string:模拟实现走进C++字符串的世界
📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C “ 登神长阶 ” 🤡往期回顾🤡:C模板入门 🌹🌹期待您的关注 🌹🌹 ❀STL之string 📒1. string…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
