【Linux】初识线程
目录
一、什么是线程:
重定义线程和进程:
执行流:
Linux中线程的实现方案:
二、再谈进程地址空间
三、小结:
1、概念:
2、进程与线程的关系:
3、线程优点:
4、线程缺点:
一、什么是线程:
首先我们回顾一下我们之前的进程概念:
如上,首先当我们创建一个进程的时候,就会有对应的task_struct来描述这个进程,如果这个进程正在运行,CPU里面有一个控制寄存器指向该进程,表示该进程在运行
然后我们的task_struct里面有对应的进程地址空间,然后通过页表映射找到对应的物理内存
接着继续创建子进程,子进程会拷贝父进程的task_struct,进程地址空间,然后通过拷贝的页表映射到不同的物理内存中,这样就可以根据不同的进程执行不同的任务了,但是每次切换进程的时候,CPU都要保存原来进程的上下文,重新调度,这样就会显得繁琐,
那么能不能只创建task_struct,然后让新task_struct和旧task_struct都指向同一个进程地址空间,同样,后面的页表也都是一样的了
这样就引入了线程,如下,新创建的task_struct就是一个个线程
线程:是进程内的一个执行分支,线程的执行粒度比进程要细
重定义线程和进程:
那么这就和我们的进程混了,那么就需要重新定义进程了:
从内核视角重新理解进程:进程是承担分配系统资源的基本实体,
进程 = 内核数据结构(task_struct) + 代码和数据,
如上,我们以前的进程并不仅仅是一个task_struct,而是上述蓝框框中的,页表及左边和映射的物理内存,
线程就是系统调度的基本单位,如上的一个个task_struct,这样,操作系统只需要针对task_struct结构即可完成调度
为什么切换线程比切换进程更加轻量化呢?
这里分两个方面:
对于进程或者线程整个生命周期:
1、创建和释放更加轻量化(生死)
2、切换更加轻量化(运行)
我们知道:
进程是有其对应的上下文的,在执行或切换进程时需要保存和恢复的运行时环境信息,以确保进程在重新调度时能继续正确运行,在其进行进程切换的时候,要先保存切换进程的上下文,然后再进行切换,将所有数据都切换(比如与用户空间直接相关的数据和代码资源,CPU寄存器中保存的进程执行状态,内核管理进程所需的控制信息和资源描述)
在CPU内部包括:运算器、控制器、寄存器、MMU、硬件级缓存(cache)等等
其中硬件级的cache又称为高速缓存,遵循计算机设计的基本原则:局部性原理,会预先加载部分用户可能访问的数据以提高效率
当切换进程时,因为存在进程间的独立性,所以cache中的进程数据就要给当前进程保存,然后别的进程再将它自己的可能将要访问的数据加载进cache中,重新开始预加载,这对于CPU是非常浪费时间的
当切换线程时,线程是属于进程的,切换线程时,cache中的数据不用切换,其中的数据可以继续使用,并且可以接着进行预加载机制
cache中的数据被称为缓存的热数据,进程切换使cache中的数据丢失再重新加载,使数据从冷数据重新变为热数据,这是很耗时间的,线程不用切换,直接使用接着预加载,所以线程更加轻量级
执行流:
执行流对应一段代码的运行轨迹,可以大到整个程序(如一个进程),也可以小到一个函数或者代码块(如一个线程)
所以执行流所执行的资源是:线程<=执行流<=进程
当进程中只有一个线程的时候,可以称为当前进程只有个执行流
当进程中有多个线程的时候,称为当前进程有多个执行流,其中每一个执行流就是一个个线程
Linux中线程的实现方案:
在Linux中,线程在进程的“内部”执行,线程在进程的地址空间中运行,因为任何执行流要执行,都要有资源,进程地址空间是进程的资源窗口,进程是承担分配系统资源的基本实体
在Linux中,线程的执行粒度要比进程更细,因为线程是执行进程代码的一部分,线程包含于进程中,所以我们之前学习的进程是不完整的,现在才是完整的
在Linux中,认为进程和线程的共同点很多,于是在写OS对其维护的代码中直接复用了进程的代码,这样就大大减少了系统调度时候的开销,在Linux中没有真正的线程的概念,只有轻量级进程
这种思想使得进程称为一款卓越的操作系统
二、再谈进程地址空间
在如上的图中,我们已经了解了大部分,但是对于页表,我们却是空白的,我们只知道虚拟地址通过页表转化为物理地址,那么具体是怎么实现的呢?
如果是直接地址映射地址的方式:
我们这里以32位系统举例:
在32位系统中:存在2^32大小的地址,这样换算出来就是4GB,这太大了,如今一般配置的电脑内存也才16GB
所以这种方式是不可能的
=========================================================================
在以前的文件系统学习了解到:
OS的读取是以 块 为单位的,一个块的大小是4kb(每个块由8个扇区组成,每个扇区大小为512字节),也就是说即使我们只读1字节,OS也会读4kb
我们的物理内存也是被分为每4kb为一小块的
对于上述的页,我们也要将其管理起来,那么怎么管理呢? ----- 先描述再组织,这样就知道物理内存中的数据是否被占用了,是否存在,是否为脏数据,方便释放管理
=========================================================================
页表的设计逻辑:
依然以我们的32位操作系统为例:
当我们拿到了一个虚拟地址,它会有32个比特位,我们将这32个比特位分成10+10+12,如下:
那么将地址分成3份之后,对应着我们页表也会有3份
以上黑色的对应这页目录,红色的对应着二级页表,蓝色的对应着对应的页框
那么怎么通过这个地址进行虚拟到物理地址之间的转化呢?
首先,将上述对应的三个部位从地址转化为十进制对应的数字
通过前10个比特位,转化的10进制数字找到对应页目录的下标,定位二级页表
然后中10个比特位,转化为10进制数字找到对应二级页表的下标,定位页框地址
最后12个比特位,作为偏移量,也就是通过页框起始地址+偏移量找到对应的物理内存
这样就完成了从虚拟地址到物理地址的转化!
对于上述可能会有一个问题 ----- 那就是如果这个偏移量会不会超过当前页框 ----- 这是不可能的,因为上述偏移量2^12正好是4kb也就是一个页框的大小
那么一个页表多大呢?
在32位操作系统中,我们知道在二级页表中存放的是地址,其中的指针变量,这里按照4字节来算,那么一个页表也就是4*1024*1024字节,那么换算出来就是4MB,这比之前的4GB来说是大大减小了
那么为什么&a只有一个地址呢?
我们知道有类型的存在,所以这里取地址就只会取首地址,然后通过类型转化成偏移量:比如如果是int就向上读取4个字节,char就向上读取1个字节,如果是自定义的类,也是如此
总的来说就是通过 起始地址 + 类型(转化成偏移量) = 读到的数据
三、小结:
1、概念:
Linux中是没有真正线程的概念的,只有轻量级进程(Light-Weight Process, LWP)是进程内的独立执行流,每个线程共享进程的资源(如内存、文件描述符等),但拥有独立的线程ID、寄存器、栈和错误码
2、进程与线程的关系:
在用户视角:
进程是资源分配的实体,而线程是这些资源的使用者
线程共享进程的虚拟地址空间和页表,但拥有独立的PCB(进程控制块)
在内核视角:
Linux内核不严格区分进程和线程,两者均通过clone()系统调用创建。区别在于是否共享地址空间:共享则为线程,独立则为进程
3、线程优点:
1、创建一个新线程的代价要比创建一个新进程小得多
2、与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多
3、线程占用的资源要比进程少很多
4、能充分利用多处理器的可并行数量
5、在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
6、计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
7、I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作
4、线程缺点:
1、性能损失:
一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器,如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变
2、健壮性降低:
编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的
3、缺乏访问控制:
进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响
4、编程难度提高:
编写与调试一个多线程程序比单线程程序困难得多
相关文章:
【Linux】初识线程
目录 一、什么是线程: 重定义线程和进程: 执行流: Linux中线程的实现方案: 二、再谈进程地址空间 三、小结: 1、概念: 2、进程与线程的关系: 3、线程优点: 4、线程…...
【Linux学习笔记】Linux基本指令分析和权限的概念
【Linux学习笔记】Linux基本指令分析和权限的概念 🔥个人主页:大白的编程日记 🔥专栏:Linux学习笔记 文章目录 【Linux学习笔记】Linux基本指令分析和权限的概念前言一. 指令的分析1.1 alias 指令1.2 grep 指令1.3 zip/unzip 指…...
uniapp登录用户名在其他页面都能响应
使用全局变量 1、在APP.vue中定义一个全局变量,然后在需要的地方引用它; <script>export default {onLaunch: function() {console.log(App Launch)this.globalData { userInfo: {} };},onShow: function() {console.log(App Show)},onHide: fu…...
ESP8266 入门(第 2 部分):使用 AT 命令
使用 AT 命令对 WiFi 收发器ESP8266编程 本教程是上一个教程 ESP8266 入门(第 1 部分)的延续。因此,简单回顾一下,在之前的教程中,我们介绍了 ESP 模块,并学习了一些基础知识。我们还使用 FTDI 串行适配器模块制作了一个开发板,该模块可以很容易地用于使用 AT 命令和 A…...
介绍一下Qt 中的QSizePolicy 布局策略
在 Qt 中,QSizePolicy 类用于描述一个控件在布局中如何分配空间,它定义了控件在水平和垂直方向上对空间的需求和响应策略。以下是对 QSizePolicy 策略的详细介绍: 基本概念 QSizePolicy 包含两个主要的属性:Policy(策…...
从ETL到数仓分层:大数据处理的“金字塔”构建之道
在当今数据驱动的时代,大数据处理已成为企业决策和业务优化的核心。而ETL(Extract, Transform, Load)作为数据处理的基石,其背后的数仓分层理念更是决定了数据处理的效率与质量。本文将深入探讨ETL工作中的数仓分层理念࿰…...
springBoot集成声明式和编程式事务的方式
一、声明式事务 前提集成了mybatisplus插件 1、pom依赖 <dependencies><!-- MyBatis-Plus 启动器 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.4&l…...
前端实现版本更新自动检测✅
🤖 作者简介:水煮白菜王,一位资深前端劝退师 👻 👀 文章专栏: 前端专栏 ,记录一下平时在博客写作中,总结出的一些开发技巧和知识归纳总结✍。 感谢支持💕💕&a…...
Python零基础学习第三天:函数与数据结构
一、函数基础 函数是什么? 想象你每天都要重复做同一件事,比如泡咖啡。函数就像你写好的泡咖啡步骤说明书,每次需要时直接按步骤执行,不用重新想流程。 # 定义泡咖啡的函数 def make_coffee(sugar1): # 默认加1勺糖 print("…...
深入了解Linux —— 调试程序
前言 我们已经学习了linux下许多的工具,vim、gcc、make/makefile等; 已经能够在linux写代码,并且进行编译运行,让程序在linux下跑起来。 但是,如果我们在写代码的时候遇见了错误;但是我们并不知道错误在哪&…...
解决VScode 连接不上问题
问题 :VScode 连接不上 解决方案: 1、手动杀死VS Code服务器进程,然后重新尝试登录 打开xshell ,远程连接服务器 ,查看vscode的进程 ,然后全部杀掉 [cxqiZwz9fjj2ssnshikw14avaZ ~]$ ps ajx | grep vsc…...
行式数据库与列式数据库区别
列式数据库(Columnar Database)和行式数据库(Row-based Database)是两种不同的数据存储和检索方式,它们在数据组织、存储结构和适用场景上有显著区别。以下是对两者的详细对比: 1. 数据存储方式 行式数据库…...
如何将本地已有的仓库上传到gitee (使用UGit)
1、登录Gitee。 2、点击个人头像旁边的加号,选择新建仓库: 3、填写仓库相关信息 4、复制Gitee仓库的地址 5、绑定我们的本地仓库与远程仓库 6、将本地仓库发布(推送)到远程仓库: 注意到此处报错ÿ…...
FIWARE:开源的物联网平台,支持设备虚拟化和数据管理
FIWARE 是一个开源的物联网(IoT)平台,旨在为物联网应用提供强大的数据管理和设备虚拟化功能。FIWARE 提供了一系列通用的 API 和组件,支持设备管理、数据采集、数据处理、数据共享和安全通信等功能,使得开发者能够快速构建和扩展物联网解决方案。以下是 FIWARE 的核心功能…...
RISC-V汇编学习(三)—— RV指令集
有了前两节对于RISC-V汇编、寄存器、汇编语法等的认识,本节开始介绍RISC-V指令集和伪指令。 前面说了RISC-V的模块化特点,是以RV32I为作为ISA的核心模块,其他都是要基于此为基础,可以这样认为:RISC-V ISA 基本整数指…...
【Linux】冯诺依曼体系与操作系统理解
🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:Linux 目录 前言 一、冯诺依曼体系结构 二、操作系统 1. 操作系统的概念 2. 操作系统存在的意义 3. 操作系统的管理方式 4. 补充:理解系统调用…...
Android15使用FFmpeg解码并播放MP4视频完整示例
效果: 1.编译FFmpeg库: 下载FFmpeg-kit的源码并编译生成安装平台库 2.复制生成的FFmpeg库so文件与包含目录到自己的Android下 如果没有prebuiltLibs目录,创建一个,然后复制 包含目录只复制arm64-v8a下...
音视频入门基础:RTP专题(16)——RTP封装音频时,音频的有效载荷结构
一、引言 《RFC 3640》和《RFC 6416》分别定义了两种对MPEG-4流的RTP封包方式,这两个文档都可以从RFC官网下载: RFC Editor 本文主要对《RFC 3640》中的音频打包方式进行简介。《RFC 3640》总共有43页,本文下面所说的“页数”是指在pdf阅读…...
3.3.2 Proteus第一个仿真图
文章目录 文章介绍0 效果图1 新建“点灯”项目2 添加元器件3 元器件布局接线4 补充 文章介绍 本文介绍:使用Proteus仿真软件画第一个仿真图 0 效果图 1 新建“点灯”项目 修改项目名称和路径,之后一直点“下一步”直到完成 2 添加元器件 点击元…...
MySQL创建数据库和表,插入四大名著中的人物
一、登录数据库并创建数据库db_ck 二、创建表t_hero 表属性包括(id,name,nickname,age,gender,address,weapon,types) mysql> create table t_hero(-> id int,-…...
matlab和FPGA联合仿真时读写.txt文件数据的方法
在FPGA开发过程中,往往需要将MATLAB生成的数据作为原始激励灌入FPGA进行仿真。为了验证FPGA计算是否正确,又需要将FPGA计算结果导入MATLAB绘图与MATLAB计算结果对比。 下面是MATLAB“写.txt”、“读.txt”,Verilog“读.txt”、“写.txt”的代…...
C++修炼之路:初识C++
Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路! 我的博客:<但凡. 我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞,关注! 引言 …...
ACE协议学习1
在多核系统或复杂SoC(System on Chip)中,不同处理器核心或IP(Intellectual Property)模块之间需要保持数据的一致性。常用的是ACE协议or CHI。 先对ACE协议进行学习 ACE协议(Advanced Microcontroller Bu…...
通俗易懂的介绍LLM大模型技术常用专业名词(通用版)
1. 神经网络 (Neural Network) 解释: 一种模拟人脑神经元结构的计算模型,用于处理复杂的数据模式。 示例: 图像识别中的卷积神经网络(CNN)。 2. 深度学习 (Deep Learning) 解释: 基于多层神经网络的机器学习方法,能够自动提取数…...
深度学习环境安装
Anaconda 3.0 下载地址 Download Success | Anaconda CUDA 下载地址 cuda_12.4.0 https://developer.nvidia.com/cuda-12-4-0-download-archive?target_osWindows&target_archx86_64&target_version11&target_typeexe_local pytorch 下载地址 (2…...
【哇! C++】类和对象(五) - 赋值运算符重载
目录 编辑 一、运算符重载 1.1 运算符重载概念 1.2 全局运算符重载 1.3 运算符重载为成员函数 二、赋值运算符重载的特性 2.1 赋值运算符重载需要注意的点 2.2 赋值运算符重载格式 2.2.1 传值返回 2.2.2 传引用返回 2.2.3 检查自己给自己赋值 三、赋值运算符重载的…...
【时序图】1.StarUML绿化
1)下载地址 官网: StarUML 如下: 2)绿化 step1:用管理员打开cmd,执行如下 npm install -g asar cd C:\Program Files\StarUML\resources //进入到StarUML的默认安装目录下面 asar extract app.asar app //反编译软件step2:把resources下的app文件夹拷贝出来到…...
mysql练习
创建数据库db_ck,再创建表t_hero,将四大名著中的主要人物都插入这个表中,将实现过程中sql提交上上来 1、创建数据库db_ck mysql> create database db_ck; 2、创建表t_hero mysql> use db_ck Database changed mysql> create table …...
数据结构(队列)
数据结构(队列) 什么是队列? 队列和栈类似,也是一类特殊的线性表。特殊之处也是在于操作上。队列:只允许在一端进行插入数据操作(入队),在另一端进行删除数据操作(出队&…...
fps项目二次总结
文章目录 角色角色蓝图动画蓝图角色蓝图与动画蓝图间的通信动画蓝图绑定在网格体上 其他蓝图角色蓝图与其他蓝图的通信通信详解单向通信:A向B与B向A互不相通A向B发送消息A:发起方:即调用方B:接收方:即提供方࿱…...
VTK笔记- 3D Widget类 vtkSplineWidget 样条部件
vtk3DWidget vtk3DWidget是用于3D交互观察器的基类,也就是各种3D小部件类的基类,主要是在三维渲染场景中生成一个可以用于控制数据的可视化实体,比如点,线段(曲线)、平面、球体、包围盒(线框&am…...
文心一言:中国大模型时代的破局者与探路者
2023年,生成式人工智能(AIGC)的浪潮席卷全球,而百度推出的“文心一言”(ERNIE Bot)作为中国AI领域的代表性产品,迅速成为行业焦点。这款基于百度自主研发的“文心大模型”打造的对话式AI工具&am…...
【芯片验证】verificationguide上的36道UVM面试题
跟上一篇一样,verificationguide上的36到UVM面试题,通义回答ds判卷。 1. What is uvm_transaction, uvm_seq_item, uvm_object, uvm_component? uvm_transaction、uvm_seq_item、uvm_object、uvm_component是什么? uvm_transaction是UVM中所有事务的基础类,用于表示仿真…...
操作系统控制台-健康守护我们的系统
引言基本准备体验功能健康守护系统诊断 收获提升结语 引言 阿里云操作系统控制平台作为新一代云端服务器中枢平台,通过创新交互模式重构主机管理体验。操作系统控制台提供了一系列管理功能,包括运维监控、智能助手、扩展插件管理以及订阅服务等。用户可以…...
基于策略模式的智能提示语生成器设计与实现——以Tkinter GUI开发为例
基于策略模式的智能提示语生成器设计与实现——以Tkinter GUI开发为例 一、引言:智能化时代的提示工程工具 在人工智能技术广泛应用的时代背景下,如何与AI模型进行有效交互已成为关键技能。本文介绍的"AI任务需求与提示语策略生成器"正是基于…...
【打卡d1】算法模拟类
题目1 题目描述: 某百货公司为了促销,采用购物打折的优惠方法,每位顾客一次购物:在1000元以上者,按 9.5 折优惠;在2000以上者,按9折优惠;在3000以上者,按8.5 折优惠;在5000 以上者,按8折优惠;编写程序&…...
7.2 奇异值分解的基与矩阵
一、奇异值分解 奇异值分解(SVD)是线性代数的高光时刻。 A A A 是一个 m n m\times n mn 的矩阵,可以是方阵或者长方形矩阵,秩为 r r r。我们要对角化 A A A,但并不是把它化成 X − 1 A X X^{-1}A X X−1AX 的形…...
3.3.2 用仿真图实现点灯效果
文章目录 文章介绍Keil生成.hex代码Proteus仿真图中导入.hex代码文件开始仿真 文章介绍 点灯之前需要准备好仿真图keil代码 仿真图参考前文:3.3.2 Proteus第一个仿真图 keil安装参考前文:3.1.2 Keil4安装教程 keil新建第一个项目参考前文:3.1…...
Docker 学习笔记:从入门到部署,实战演练全流程!
📌 开篇:为什么要学 Docker? 还在为环境不一致、部署麻烦、依赖冲突头疼吗?Docker 让一切变得简单!作为现代开发和运维的神器,Docker 让我们可以用 一句命令 解决 “在我电脑上能跑” 的问题。今天&#x…...
本地搭建DeepSeek R1模型 + 前端
本地搭建DeepSeek R1模型 前端 配置: 操作系统:windows11 CPU:i5 13600KF GPU:英伟达4070 12GB 内存:16G DDR5 硬盘:1TB 模型安装 本文采用Ollama进行安装。Ollama安装比较简单。 官网࿱…...
MyBatis增删改查:静态与动态SQL语句拼接及SQL注入问题解析
MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作。本文将深入探讨 MyBatis 中的增删改查操作,重点讲解静态与动态 SQL 语句的拼接,并分析 S…...
Unity入门学习笔记(Day01)
一.认识unity工作面板 1.1.project window(项目面板) 显示当前项目中的所有文件和目录,包含了项目里面所有的资源文件 1.2.console window(输出面板) 显示当前游戏开发中生成的警告错误 1.3.hierarchy window&…...
教务考试管理系统-Sprintboot vue
一、前言 1.1 实践目的和要求 本次实践的目的是为了帮助学生强化对实践涉及专业技术知识的理解,掌握专业领域中软件知识的应用方法,并了解软件工程在具体行业领域的发展趋势。通过培养学生利用软件工程方法分析、设计并完成具体行业软件开发的能力&…...
GHCTF2025--Web
upload?SSTI! import os import refrom flask import Flask, request, jsonify,render_template_string,send_from_directory, abort,redirect from werkzeug.utils import secure_filename import os from werkzeug.utils import secure_filenameapp Flask(__name__)# 配置…...
文件上传漏洞(upload-labs)
目录 Pass-01(前端绕过) (1)JavaScript (2)Burpsuite(改后缀) Pass-02(IMME类型 ) burpsuite(改文件类型) Pass-03(黑名单绕过) …...
图片的拖拽+缩放
效果图: <script setup lang"ts"> import { onMounted, ref } from vue; import ImgBg from /assets/img/bg.jpg import Img1 from /assets/img/1.jpgconst innerStyle ref({left: 0,top: 0,width: 100,height: 0 }) const wrapStyle ref({width:…...
Windows软件插件-音视频文件读取器
下载本插件 本插件读取音频和视频文件,输出音频样本和视频样本,音频样本为16位PCM,采样率48000;视频样本为RGB32。大部分音频和视频文件格式都可以读取。本插件类型为DLL。 本插件是通过创建媒体基础“源读取器”对象实现读取音视…...
考研数一复习之拉格朗日中值定理求解函数极限
最近在复习考研数学,只是简单做题过于乏味,因此便总结了一些笔记,后续若有空,也会将自己的复习笔记分享出来。本篇,我们将重点讲解拉格朗日中值定理在求解函数极限中的应用。同时,作者本人作为python领域创作者,还将在本文分享使用sympy求解高数中函数极…...
聊天服务器分布式改造
目前的聊天室是单节点的,无论是http接口还是socket接口都在同一个进程,无法承受太多人同时在线,容灾性也非常差。因此,一个成熟的IM产品一定是做成分布式的,根据功能分模块,每个模块也使用多个节点并行部署…...
C++11的一些特性
目录 一、C11简介 二、统一的列表初始化 2.1 {}初始化 2.2 std::initializer_list 三、声明 3.1 auto 3.2 decltype 3.3 nullptr 四、范围for循环 五、智能指针 5.1 RAII 5.2 智能指针的原理 5.3 std::auto_ptr…...