《网校 21天学通C++(第六版)-365资源论坛提供》第20章 STL set与multiset【技能收获】学完可掌握:C/C++ 网络编程、Vue / 前端工程化。课程以实战为导向,覆盖从基础概念到完整项目落地的关键步骤,配套章节笔记便于课后复盘与面试前快速回顾。【学习建议】建议按目录顺序学习,先打基础再进入综合实战章节;每完成 2~3 节可结合笔记整理一份学习小结,最终尝试独立复现一套完整 Demo 写入个人作品集。【就业发展】可面向岗位:Linux 运维工程师、SRE、云计算工程师、DevOps 工程师。云原生与自动化运维仍是企业 IT 刚需方向,认证 + 实战项目组合能显著提升面试通
先说结论:这套《21天学通C++》第六版的网校视频,最值钱的部分不在前七天,而在第14章之后。如果你已经能写简单的类、能看懂指针和引用,完全可以从第12章往后跳着看;反之,如果你连for循环里i++和++i的区别都说不清,那就老老实实从第1章啃起,别急着翻STL。
21天的节奏安排其实是个幌子——它把C++拆成了三段:语法基础、面向对象、标准库与泛型。前7天讲变量、控制流、函数、数组指针,这部分内容是任何一本C++书都有的,视频能给你的额外价值只有讲师的板书习惯和口头强调的易错点。第8到14天进入类和继承、多态、运算符重载,这里开始出现"看视频比看书快"的地方:虚函数表怎么画、构造析构顺序怎么走、拷贝构造什么时候被调用,有人边写边讲一遍,比你自己对着书推半天要省时间。
第14章之后才是这套课真正拉开差距的地方。模板、STL容器、迭代器、算法、智能指针,这些内容如果只靠看书,很容易停在"知道有这个玩意儿"的层面。视频里跟着敲一遍map的插入删除、set去重、vector扩容,印象会深很多。第20章的 set 与 multiset 正好卡在这个位置上,是检验你前面迭代器和仿函数有没有学扎实的试金石。
很多人学STL的顺序是 vector→map→set,把 set 当成"map 只要 key 的版本"一带而过。但 set 和 multiset 的差异恰好是面试里爱问的点:multiset 允许重复元素,equal_range和count的语义就和 set 不一样;底层红黑树的插入删除复杂度、迭代器失效规则、自定义比较函数的写法,这些在 multiset 场景下更容易暴露理解漏洞。如果你手头有这套课,第20章建议不要倍速,跟着敲一遍增删查改,再自己写一个用 multiset 统计词频的小例子,比刷十道选择题管用。
const、&、explicit这类修饰符的位置——这些是C++区别于C的关键细节。这套课适合有C语言基础、想把C++当成工具而不是研究对象的人。它不深挖语言标准演进,也不讲模板元编程的花活,胜在节奏快、覆盖全、能让你在较短时间内把C++的主要语法和STL用起来。但如果你目标是啃STL源码或者写高性能模板库,这套课只能算热身,看完第20章之后还得自己去找更专门的资料补。
另外提醒一句:摘要里提到的网络编程、Vue、前端工程化、Linux运维、SRE那些方向,和这套C++课的正文内容基本不是一回事。别被那些标签带偏,这门课的核心就是C++语言本身加STL,学完能写命令行程序和小型控制台项目,离"网络编程实战"还有一段路要走。
第20章 STL set与multiset
课程推荐
《网校 21天学通C++(第六版)-365资源论坛提供》第20章 STL set与multiset【技能收获】学完可掌握:C/C++ 网络编程、Vue / 前端工程化。课程以实战为导向,覆盖从基础概念到完整项目落地的关键步骤,配套章节笔记便于课后复盘与面试前快速回顾。【学习建议】建议按目录顺序学习,先打基础再进入综合实战章节;每完成 2~3 节可结合笔记整理一份学习小结,最终尝试独立复现一套完整 Demo 写入个人作品集。【就业发展】可面向岗位:Linux 运维工程师、SRE、云计算工程师、DevOps 工程师。云原生与自动化运维仍是企业 IT 刚需方向,认证 + 实战项目组合能显著提升面试通过率,适合向中高级运维或架构岗进阶。 若你已有一定编程或运维基础,本课程可帮助你在现有技能栈上快速叠加热门方向能力,提升求职时的项目说服力与薪资谈判空间。
视频目录(453 节)
* 1.1 C++简史
* 1.1.1 解释器和编译器
* 1.1.2 不断变化的需求和平台
* 1.1.3 过程化编程、结构化编程和面向对象编程
* 1.1.4 面向对象编程(OOP)
* 1.1.5 C++和面向对象编程
* 1.2 C++的发展历程
* 1.3 应该先学习C语言吗
* 1.4 微软的C++托管扩展
* 1.5 ANSI标准
* 1.6 编程准备
* 1.7 开发环境
* 1.8 创建程序的步骤
* 1.8.1 用编译器生成对象文件
* 1.8.2 用链接器生成可执行文件
* 1.9 程序开发周期
* 1.10 HELLO.cpp:第一个C++程序
* 1.11 编译器初步
* 1.12 编译错误
* 2.1 一个简单程序
* 2.2 cout简介
* 2.3 使用标准名称空间
* 2.4 对程序进行注释
* 2.4.1 注释的类型
* 2.4.2 使用注释
* 2.4.3 有关注释的警告
* 2.5 函数
* 2.5.1 使用函数
* 2.5.2 方法和函数
* 3.1 什么是变量
* 3.1.1 将数据存储在内存中
* 3.1.2 预留内存
* 3.1.3 整型变量的大小
* 3.1.4 基本变量类型
* 3.2 定义变量
* 3.2.1 区分大小写
* 3.2.2 命名规则
* 3.2.3 关键字
* 3.3 确定变量类型占用的内存量
* 3.4 一次创建多个变量
* 3.5 给变量赋值
* 3.6 使用typedef创建别名
* 3.7 何时使用short和long
* 3.7.1 unsigned整型变量的回绕
* 3.7.2 signed整型变量的回绕
* 3.8 使用字符
* 3.8.1 字符和数字
* 3.8.2 特殊打印字符
* 3.9 常量
* 3.9.1 字面常量
* 3.9.2 符号常量
* 3.10 枚举常量
* 4.1 什么是数组
* 4.1.1 访问数组元素
* 4.1.2 在数组末尾后写入数据
* 4.1.3 护栏柱错误
* 4.1.4 初始化数组
* 4.1.5 声明数组
* 4.2 使用多维数组
* 4.2.1 声明多维数组
* 4.2.2 初始化多维数组
* 4.3 字符数组和字符串
* 4.4 使用方法strcpy()和strncpy()
* 4.5 string类
* 5.1 语句简介
* 5.1.1 使用空白
* 5.1.2 语句块和复合语句
* 5.2 表达式
* 5.3 使用运算符
* 5.3.1 赋值运算符
* 5.3.2 数学运算符
* 5.3.3 整数除法和求模
* 5.4 结合使用赋值运算符与数学运算符
* 5.5 递增和递减
* 5.6 理解运算符优先级
* 5.7 括号的嵌套
* 5.8 真值的本质
* 5.9 if语句
* 5.9.1 缩进风格
* 5.9.2 else语句
* 5.9.3 高级if语句
* 5.10 在嵌套if语句中使用大括号
* 5.11 使用逻辑运算符
* 5.11.1 逻辑AND运算符
* 5.11.2 逻辑OR运算符
* 5.11.3 逻辑NOT运算符
* 5.12 简化求值
* 5.13 关系运算符的优先级
* 5.14 再谈真和假
* 5.15 条件运算符(三目运算符)
* 6.1 什么是函数
* 6.2 返回值、参数和实参
* 6.3 声明和定义函数
* 6.3.1 函数原型
* 6.3.2 定义函数
* 6.4 函数的执行
* 6.5 确定变量的作用域
* 6.5.1 局部变量
* 6.5.2 作用域为语句块的局部变量
* 6.6 参数是局部变量
* 6.6.1 全局变量
* 6.6.2 有关全局变量的注意事项
* 6.7 创建函数语句时的考虑因素
* 6.8 再谈函数实参
* 6.9 再谈返回值
* 6.10 默认参数
* 6.11 重载函数
* 6.12 函数特有的主题
* 6.12.1 内联函数
* 6.12.2 递归
* 6.13 函数的工作原理
* 6.13.1 抽象层次
* 6.13.2 划分RAM
* 6.13.3 堆栈和函数
* 7.1 循环
* 7.1.1 循环的鼻祖:goto
* 7.1.2 为何避免使用goto语句
* 7.2 使用while循环
* 7.2.1 更复杂的while语句
* 7.2.2 continue和break简介
* 7.2.3 while(true)循环
* 7.3 实现do...while循环
* 7.4 使用do...while
* 7.5 for循环
* 7.5.1 高级for循环
* 7.5.2 空for循环
* 7.5.3 循环嵌套
* 7.5.4 for循环中声明的变量的作用域
* 7.6 循环小结
* 7.7 使用switch语句控制程序流程
* 8.1 什么是指针
* 8.1.1 内存简介
* 8.1.2 获取变量的内存地址
* 8.1.3 将变量的地址存储到指针中
* 8.1.4 指针名
* 8.1.5 获取指针指向的变量的值
* 8.1.6 使用间接运算符解除引用
* 8.1.7 指针、地址和变量
* 8.1.8 使用指针来操纵数据
* 8.1.9 查看地址
* 8.1.10 指针和数组名
* 8.1.11 数组指针和指针数组
* 8.2 为什么使用指针
* 8.3 栈和自由存储区(堆)
* 8.3.1 使用关键字new分配内存
* 8.3.2 使用关键字delete归还内存
* 8.4 再谈内存泄漏
* 8.5 在自由存储区上创建对象
* 8.6 删除自由存储区中的对象
* 8.7 迷途指针
* 8.8 使用const指针
* 9.1 什么是引用
* 9.2 将地址运算符用于引用
* 9.3 空指针和空引用
* 9.4 按引用传递函数参数
* 9.4.1 使用指针让swap()管用
* 9.4.2 使用引用来实现swap()
* 9.5 返回多个值
* 9.6 按引用传递以提高效率
* 9.6.1 传递const指针
* 9.6.2 用引用代替指针
* 9.7 何时使用引用和指针
* 9.8 混合使用引用和指针
* 9.9 返回指向不在作用域中的对象的引用
* 10.1 C++是面向对象的吗
* 10.2 创建新类型
* 10.3 类和成员简介
* 10.3.1 声明类
* 10.3.2 有关命名规则的说明
* 10.3.3 定义对象
* 10.3.4 类与对象
* 10.4 访问类成员
* 10.4.1 给对象而不是类赋值
* 10.4.2 类不能有没有声明的功能
* 10.5 私有和公有
* 10.6 实现类方法
* 10.7 添加构造函数和析构函数
* 10.7.1 默认构造函数和析构函数
* 10.7.2 使用默认构造函数
* 10.8 const成员函数
* 10.9 将类声明和方法定义放在什么地方
* 10.10 内联实现
* 10.11 将其他类用作成员数据的类
* 10.12 探索结构
* 11.1 什么是继承
* 11.1.1 继承和派生
* 11.1.2 动物世界
* 11.1.3 派生的语法
* 11.2 私有和保护
* 11.3 构造函数和析构函数的继承性
* 11.4 覆盖基类函数
* 11.4.1 隐藏基类的方法
* 11.4.2 调用基类方法
* 11.5 虚方法
* 11.5.1 虚函数的工作原理
* 11.5.2 通过基类指针访问派生类的方法
* 11.5.3 切除
* 11.5.4 创建虚析构函数
* 11.5.5 虚复制构造函数
* 11.5.6 使用虚方法的代价
* 11.6 私有继承
* 11.6.1 使用私有继承
* 11.6.2 私有继承和聚合(组合)
* 12.1 单继承存在的问题
* 12.1.1 提升
* 12.1.2 向下转换
* 12.1.3 将对象添加到链表中
* 12.2 多重继承
* 12.2.1 多重继承对象的组成部分
* 12.2.2 多重继承对象中的构造函数
* 12.2.3 避免歧义
* 12.2.4 从共同基类继承
* 12.2.5 虚继承
* 12.2.6 多重继承存在的问题
* 12.2.7 混合(功能)类
* 12.3 抽象数据类型
* 12.3.1 纯虚函数
* 12.3.2 实现纯虚函数
* 12.3.3 复杂的抽象层次结构
* 12.3.4 哪些类是抽象的
* 13.1 C++中的运算符
* 13.2 单目运算符
* 13.2.1 单目运算符的类型
* 13.2.2 单目递增与单目递减运算符
* 13.2.3 解除引用运算符*与成员选择运算符-的编程
* 13.2.4 转换运算符的编程
* 13.3 双目运算符
* 13.3.1 双目运算符的类型
* 13.3.2 双目加与双目减运算符的编程
* 13.3.3 运算符+=与-=的编程
* 13.3.4 重载比较运算符
* 13.3.5 重载运算符、、=和=
* 13.3.6 下标运算符
* 13.4 operator()函数
* 13.5 不能重新定义的运算符
* 14.1 什么是类型转换
* 14.2 为何需要类型转换
* 14.3 为何有些C++程序员不喜欢C风格类型转换
* 14.4 C++类型转换运算符
* 14.4.1 使用static_cast
* 14.4.2 使用dynamic_cast和运行阶段类型识别
* 14.4.3 使用reinterpret_cast
* 14.4.4 使用const_cast
* 14.5 C++类型转换运算符存在的问题
* 15.1 预处理器与编译器
* 15.2 预处理器指令#define
* 15.3 宏函数
* 15.3.1 为什么要使用括号
* 15.3.2 宏与类型安全问题
* 15.3.3 宏与函数及模板之比较
* 15.3.4 内联函数
* 15.4 模板简介
* 15.4.1 模板声明语法
* 15.4.2 各种类型的模板声明
* 15.4.3 模板类
* 15.4.4 模板的实例化和具体化
* 15.4.5 模板与类型安全
* 15.4.6 使用多个参数声明模板
* 15.4.7 使用默认参数来声明模板
* 15.4.8 一个模板示例
* 15.4.9 在实际C++编程中使用模板
* 16.1 STL容器
* 16.1.1 顺序容器
* 16.1.2 关联容器
* 16.1.3 选择正确的容器
* 16.2 STL迭代器
* 16.3 STL算法
* 16.4 使用迭代器在容器和算法之间交互
* 17.1 为何需要字符串操作类
* 17.2 使用STL string类
* 17.2.1 实例化STL string及复制
* 17.2.2 访问string及其内容
* 17.2.3 字符串连接
* 17.2.4 在string中查找字符或子字符串
* 17.2.5 截短STL string
* 17.2.6 字符串反转
* 17.2.7 字符串的大小写转换
* 17.3 基于模板的STL string实现
* 18.1 std::vector的特点
* 18.2 典型的vector操作
* 18.2.1 实例化vector
* 18.2.2 在vector中插入元素
* 18.2.3 访问vector中的元素
* 18.2.4 删除vector中的元素
* 18.3 理解size()和capacity()
* 18.4 STL deque 类
* 19.1 std::list的特点
* 19.2 基本的list操作
* 19.2.1 实例化std::list对象
* 19.2.2 在list开头插入元素
* 19.2.3 在list末尾插入元素
* 19.2.4 在list中间插入元素
* 19.2.5 删除list中的元素
* 19.3 对list中元素进行反转和排序
* 19.3.1 反转元素的排列顺序
* 19.3.2 元素排序
* 20.1 简介
* 20.2 STL set和multiset的基本操作
* 20.2.1 实例化std::set对象
* 20.2.2 在STL set或multiset中插入元素
* 20.2.3 在STL set或multiset中查找元素
* 20.2.4 删除STL set或multiset中的元素
* 20.3 使用STL set和multiset的优缺点
* 21.1 简介
* 21.2 STL map和multimap的基本操作
* 21.2.1 实例化std::map对象
* 21.2.2 在STL map或multimap中插入元素
* 21.2.3 在STL map或multimap中查找元素
* 21.2.4 删除STL map或multimap中的元素
* 21.3 提供自定义的排序谓词
* 22.1 函数对象与谓词的概念
* 22.2 函数对象的典型用途
* 22.2.1 一元函数
* 22.2.2 一元谓词
* 22.2.3 二元函数
* 22.2.4 二元谓词
* 23.1 什么是STL算法
* 23.2 STL算法的分类
* 23.2.1 非变序算法
* 23.2.2 变序算法
* 23.3 STL算法的应用
* 23.3.1 计算元素个数与查找元素
* 23.3.2 在集合中搜索元素或序列
* 23.3.3 将容器中的元素初始化为指定值
* 23.3.4 用for_each处理范围内的元素
* 23.3.5 使用std::transform对范围进行变换
* 23.3.6 复制和删除操作
* 23.3.7 替换值以及替换满足给定条件的元素
* 23.3.8 排序、在有序集合中搜索以及删除重复元素
* 23.3.9 将范围分区
* 23.3.10 在有序集合中插入元素
* 24.1 栈和队列的行为特征
* 24.1.1 栈
* 24.1.2 队列
* 24.2 使用STL stack类
* 24.2.1 实例化stack
* 24.2.2 stack的成员函数
* 24.3 使用STL queue类
* 24.3.1 实例化queue
* 24.3.2 queue的成员函数
* 24.4 使用STL优先级队列
* 24.4.1 实例化priority_queue类
* 24.4.2 priority_queue的成员函数
* 25.1 bitset类
* 25.2 使用std::bitset及其成员
* 25.2.1 std:bitset的运算符
* 25.2.2 std::bitset的成员方法
* 25.3 vectorbool
* 25.3.1 实例化vectorbool
* 25.3.2 使用vectorbool
* 26.1 什么是智能指针
* 26.1.1 使用常规(原始)指针有何问题
* 26.1.2 智能指针有何帮助
* 26.2 智能指针是如何实现的
* 26.3 智能指针类型
* 26.3.1 深度复制
* 26.3.2 写时复制机制
* 26.3.3 引用计数智能指针
* 26.3.4 引用链接智能指针
* 26.3.5 破坏性复制
* 26.4 使用std::auto_ptr
* 26.5 流行的智能指针库
* 27.1 流概述
* 27.1.1 数据流的封装
* 27.1.2 理解缓冲技术
* 27.2 流和缓冲区
* 27.3 标准I/O对象
* 27.4 重定向标准流
* 27.5 使用cin进行输入
* 27.5.1 输入字符串
* 27.5.2 字符串的问题
* 27.5.3 的返回值
* 27.6 cin的其他成员函数
* 27.6.1 单字符输入
* 27.6.2 从标准输入读取字符串
* 27.6.3 使用cin.ignore()
* 27.6.4 查看和插入字符:peek()和putback()
* 27.7 使用cout进行输出
* 27.7.1 刷新输出
* 27.7.2 执行输出的函数
* 27.7.3 控制符、标记和格式化指令
* 27.8 流和printf()函数之比较
* 27.9 文件输入和输出
* 27.9.1 使用ofstream
* 27.9.2 条件状态
* 27.9.3 打开文件进行输入和输出
* 27.9.4 修改ofstream打开文件时的默认行为
* 27.10 二进制文件和文本文件
* 27.11 命令行处理
* 28.1 程序中的各种错误
* 28.2 异常的基本思想
* 28.2.1 异常处理的组成部分
* 28.2.2 手工引发异常
* 28.2.3 创建异常类
* 28.3 使用try块和catch块
* 28.4 捕获异常的工作原理
* 28.4.1 使用多条catch语句
* 28.4.2 异常层次结构
* 28.5 异常中的数据及给异常对象命名
* 28.6 异常和模板
* 28.7 没有错误的异常
* 28.8 bug和调试
* 28.8.1 断点
* 28.8.2 监视点
* 28.8.3 查看内存
* 28.8.4 查看汇编代码
* 28.9 总结
* 28.10 问与答
* 28.11 作业
* 28.11.1 测验
* 28.11.2 练习
* 29.1 预处理器和编译器
* 29.2 预编译器指令#define
* 29.2.1 使用#define定义常量
* 29.2.2 将#define用于检测
* 29.2.3 预编译器命令#else
* 29.3 包含和防范多重包含
* 29.4 字符串操纵
* 29.4.1 字符串化
* 29.4.2 拼接
* 29.5 预定义的宏
* 29.6 assert()宏
* 29.6.1 使用assert()进行调试
* 29.6.2 assert()与异常之比较
* 29.6.3 副作用
* 29.6.4 类的不变量
* 29.6.5 打印中间值
* 29.7 位运算
* 29.7.1 “与”运算符
* 29.7.2 “或”运算符
* 29.7.3 “异或”运算符
* 29.7.4 “求反”运算符
* 29.7.5 设置位
* 29.7.6 清除位
* 29.7.7 反转位
* 29.7.8 位字段
* 29.8 编程风格
* 29.8.1 缩进
* 29.8.2 大括号
* 29.8.3 长代码行和函数长度
* 29.8.4 格式化switch语句
* 29.8.5 程序文本
* 29.8.6 标识符命名
* 29.8.7 名称的拼写和大写
* 29.8.8 注释
* 29.8.9 设置访问权限
* 29.8.10 类定义
* 29.8.11 包含文件
* 29.8.12 使用assert()
* 29.8.13 使用const
* 29.9 C++开发工作的下一步
* 29.9.1 从何处获得帮助和建议
* 29.9.2 相关的C++主题:托管C++、C#和微软的.NET