简介
- 在C++编程中, NaN(Not a number)是浮点数类型(例如float, double, long double)中的一种特殊值,用于表示无法定义的数值或者操作结果。NaN在数值计算和科学计算中十分常见,正确理解和处理NaN对于编写健壮和可靠的代码至关重要。
rsync
是一个用于在本地或远程同步文件和目录的开源实用工具。它非常强大和灵活,支持递归传输、保持文件权限、压缩传输等功能,使其成为文件同步和备份的首选工具之一。
以下是 rsync
的一些常用选项和示例:
-a, --archive
:归档模式,等同于 -rlptgoD
,保留文件的权限、时间戳、符号链接等。-v, --verbose
:详细模式,显示传输过程中的详细信息。-z, --compress
:在传输过程中压缩文件以节省带宽。-P
:显示传输进度并部分保留已传输的文件(等同于 --partial --progress
)。--exclude
:排除指定的文件或目录。--delete
:删除目标目录中在源目录中不存在的文件。1 | rsync -av /source/directory /destination/directory |
将 /source/directory
复制到 /destination/directory
。
1 | rsync -av /local/directory user@remote_host:/remote/directory |
将本地目录 /local/directory
复制到远程主机 remote_host
的 /remote/directory
。
1 | rsync -av user@remote_host:/remote/directory /local/directory |
将远程主机 remote_host
的 /remote/directory
复制到本地目录 /local/directory
。
--exclude
排除特定目录1 | rsync -av --exclude 'exclude_directory' /source/directory user@remote_host:/remote/directory |
将本地目录 /source/directory
复制到远程主机 remote_host
的 /remote/directory
,但排除 exclude_directory
目录。
同步本地目录
1 | rsync -av /home/user/data /backup |
将 /home/user/data
目录同步到 /backup
目录。
排除特定目录
1 | rsync -av --exclude 'tmp' /home/user/data /backup |
将 /home/user/data
目录同步到 /backup
目录,但排除 tmp
目录。
同步到远程主机
1 | rsync -avz /home/user/data user@remote_host:/backup |
将本地 /home/user/data
目录同步到远程主机 remote_host
的 /backup
目录,并在传输过程中进行压缩。
从远程主机同步到本地
1 | rsync -avz user@remote_host:/backup /home/user/data |
将远程主机 remote_host
的 /backup
目录同步到本地的 /home/user/data
目录,并在传输过程中进行压缩。
显示进度
1 | rsync -avP /home/user/data user@remote_host:/backup |
将本地 /home/user/data
目录同步到远程主机 remote_host
的 /backup
目录,并显示传输进度。
rsync
是一个非常强大且灵活的工具,适用于各种文件同步和备份需求。通过熟练使用 rsync
的各种选项,你可以高效地完成复杂的文件传输和同步任务。
rsync
是一个强大的文件同步工具,常用于在本地或远程主机之间复制和同步文件和目录。它支持增量传输、保持文件权限、压缩传输等功能。以下是 rsync
的详细说明和一些示例。
1 | rsync [OPTION]... SRC [SRC]... DEST |
SRC
:源文件或目录DEST
:目标文件或目录-a, --archive
:归档模式,相当于 -rlptgoD
,保留文件属性。-r, --recursive
:递归处理目录。-l, --links
:保留符号链接。-p, --perms
:保留文件权限。-t, --times
:保持文件修改时间。-g, --group
:保留文件组信息。-o, --owner
:保留文件所有者信息。-D
:保留设备文件和特殊文件。-v, --verbose
:详细输出。-z, --compress
:在传输过程中压缩文件。-P
:显示传输进度和部分传输的文件(等同于 --partial --progress
)。--partial
:保留部分传输的文件,以便恢复。--progress
:显示传输进度。--exclude
:指定排除的文件或目录模式。--delete
:删除目标目录中在源目录中不存在的文件。--bwlimit=RATE
:限制 I/O 带宽,单位为 KB/s。-e, --rsh=COMMAND
:指定远程 shell 程序。--checksum
:基于文件校验和进行比较,而不是文件大小和修改时间。将本地目录 /source/directory
复制到 /destination/directory
:
1 | rsync -av /source/directory /destination/directory |
将本地目录 /local/directory
复制到远程主机 remote_host
的 /remote/directory
:
1 | rsync -av /local/directory user@remote_host:/remote/directory |
将远程主机 remote_host
的 /remote/directory
复制到本地目录 /local/directory
:
1 | rsync -av user@remote_host:/remote/directory /local/directory |
将本地目录 /source/directory
复制到远程主机 remote_host
的 /remote/directory
,但排除 exclude_directory
:
1 | rsync -av --exclude 'exclude_directory' /source/directory user@remote_host:/remote/directory |
在传输过程中显示进度:
1 | rsync -avP /source/directory user@remote_host:/remote/directory |
将本地目录 /source/directory
同步到远程主机 remote_host
的 /remote/directory
,并删除目标目录中多余的文件:
1 | rsync -av --delete /source/directory user@remote_host:/remote/directory |
将本地目录 /source/directory
复制到远程主机 remote_host
的 /remote/directory
,并限制传输带宽为 500 KB/s:
1 | rsync -avz --bwlimit=500 /source/directory user@remote_host:/remote/directory |
通过 SSH 进行文件传输:
1 | rsync -avz -e ssh /source/directory user@remote_host:/remote/directory |
基于文件校验和进行比较,而不是文件大小和修改时间:
1 | rsync -avz --checksum /source/directory user@remote_host:/remote/directory |
rsync
是一个非常强大且灵活的工具,可以满足各种文件同步和备份需求。通过掌握 rsync
的各种选项和用法,你可以高效地完成复杂的文件传输和同步任务。
在 Linux 上使用 rsync
拷贝目录并且忽略指定目录的具体步骤如下。假设你要拷贝 /source/directory
到目标目录 /destination/directory
,但要忽略 ignore_directory
目录。
1 | rsync -av --exclude 'ignore_directory' /source/directory/ /destination/directory/ |
-a, --archive
:归档模式,表示递归复制目录,并保持文件属性。-v, --verbose
:详细模式,显示传输过程中的信息。--exclude 'ignore_directory'
:指定要排除的目录 ignore_directory
。/source/directory/
:源目录路径,末尾的 /
表示拷贝目录内的内容。/destination/directory/
:目标目录路径,末尾的 /
表示将内容复制到该目录中。假设有如下目录结构:
1 | /source/directory/ |
使用上述 rsync
命令:
1 | rsync -av --exclude 'ignore_directory' /source/directory/ /destination/directory/ |
结果是:
1 | /destination/directory/ |
--exclude
选项:1 | rsync -av --exclude 'ignore_directory1' --exclude 'ignore_directory2' /source/directory/ /destination/directory/ |
--exclude-from
选项从文件中读取排除的目录和文件列表。假设排除列表文件 exclude-list.txt
内容如下:1 | ignore_directory1 |
使用命令:
1 | rsync -av --exclude-from='exclude-list.txt' /source/directory/ /destination/directory/ |
通过以上方法,你可以使用 rsync
高效地复制目录,同时忽略指定的目录或文件。这些选项提供了灵活的排除机制,使 rsync
成为处理文件同步和备份任务的强大工具。
使用 rsync
命令可以实现远程拷贝目录并且忽略指定目录。以下是详细步骤和示例。
假设你要将本地的 /source/directory
目录拷贝到远程主机 remote_host
的 /destination/directory
,但要忽略 ignore_directory
目录。
1 | rsync -av --exclude 'ignore_directory' /source/directory/ user@remote_host:/destination/directory/ |
-a, --archive
:归档模式,表示递归复制目录,并保持文件属性。-v, --verbose
:详细模式,显示传输过程中的信息。--exclude 'ignore_directory'
:指定要排除的目录 ignore_directory
。/source/directory/
:源目录路径,末尾的 /
表示拷贝目录内的内容。user@remote_host:/destination/directory/
:目标目录路径,格式为 user@host:/path
。假设有如下本地目录结构:
1 | /source/directory/ |
使用上述 rsync
命令:
1 | rsync -av --exclude 'ignore_directory' /source/directory/ user@remote_host:/destination/directory/ |
结果是远程主机 remote_host
上的 /destination/directory/
目录结构为:
1 | /destination/directory/ |
如果你有多个目录或文件需要排除,可以使用多个 --exclude
选项:
1 | rsync -av --exclude 'ignore_directory1' --exclude 'ignore_directory2' /source/directory/ user@remote_host:/destination/directory/ |
你也可以使用 --exclude-from
选项从文件中读取排除的目录和文件列表。假设排除列表文件 exclude-list.txt
内容如下:
1 | ignore_directory1 |
使用命令:
1 | rsync -av --exclude-from='exclude-list.txt' /source/directory/ user@remote_host:/destination/directory/ |
通过以上方法,你可以使用 rsync
高效地实现远程目录拷贝,同时忽略指定的目录或文件。这些选项提供了灵活的排除机制,使 rsync
成为处理远程文件同步和备份任务的强大工具。
图像处理
计算机视觉算法
深度学习框架
容易犯的错误
有过工作经验与应届生的简历还是要有很大区别。你在职场中的历练即使只有短短的一年时间,对于用人单位来说也算是有工作经验,更何况你已经任职了几年的时间,这些经历写在简历中,这些对于你寻找新的工作都是非常有益处的。如果你面临第一次跳槽,把简历从文档中“捞”出来,重新润色
重新撰写简历可以考虑删减掉在校经历,只要体现你的最高学历和所学专业即可。例如:学习状况;校内社团学生会活动经历;隐去在校内的职务,毕竟这些只是代表你在学生时期的一定历练,对于工作多年的职场人并不适用。如果是真的没什么好写的内容,那就还是选择写上吧……就当充数了。
刷新职场中的工作经历:将职场中的工作经历详尽描述。几年的工作时间一定累计了相应的工作经验,针对自己的岗位职责,工作成绩做到有条理的陈述,并将工作中取得的成绩用数据、百分比进行详细阐述。如果有明确的项目执行经验,简历中最好也明确表述。仅仅用职位头衔并不能让HR更直观的看出一个人的实际能力,是否是公司所需要的人才,高质量的项目执行经验会为简历增色不少。用直观的数字体现你获得的成就、业绩。把自己获得过的奖项之类都可以放到简历上,会让HR更加鲜明地感受到你的优秀。
认真的表达你第一次跳槽的原因.金三银四最适合找工作的黄金时间段,金三银四的大意是:最好的时间是三月,其次是四月.同理于金九银十,最好的时间是九月,其次是十月
为什么要更写简历?
突出自己的优势
写出自己的职业规划
诚实表达自己的跳槽意图
如果自己没有头绪,就花点小钱,找人帮你修改.
项目经验:突出你在过去的三到四年中参与和完成的项目。描述你的角色、项目规模、使用的技术和工具,并强调你取得的成果和贡献。包括具体的项目细节和解决方案,以及任何与项目相关的指标或指导性数据
技能和技术栈:列出你熟悉的编程语言、框架、库和工具。强调你对Python的扎实掌握以及相关的Web开发、数据库管理、测试框架、版本控制系统等方面的技能。如果你有其他编程语言或领域专长(如数据科学、机器学习等),也应在技能部分进行适当的展示
贡献和成果:突出你在工作中取得的具体成果和贡献。这可能包括优化性能、提高系统可靠性、实施新功能或改进现有功能等方面的工作。使用具体的数字和数据来量化你的成就,如优化代码效率带来的性能提升、减少bug数量、增加用户数量等
自我学习和持续发展:强调你对技术的持续学习和成长。提及你参与的培训、研讨会、技术社区的活动,以及你通过阅读书籍、学习新技术等方式自我提升的经验。这展示了你对个人发展和保持行业领先的承诺
边缘计算项目的总结文档
项目名称: 智慧工地视频分析盒子
项目需求: 智慧工地盒子产品实现对工地现场中一些违规现象及时发现和提醒,提高管理效率
我负责的模块是后端服务器
后端服务器向前端提供数据支持,
与底层引擎交互,对结构化数据的处理
后端服务器和前端的通讯
后端服务器与底层引擎的通讯
机器人项目的总结
项目名称: 机场行李搬运项目
项目需求: 机械臂替代人工,完成行李从传送带到行李车的装载工作
难点
系统功能
我负责的模块是
master
robot
job
每个节点有一个难点
master
robot
job
数据结构相关笔记
数据结构(data structure)是计算机中存储,组织数据的方式
数据结构是一种具有一定逻辑关系,在计算机中应用某种数据结构,并且封装了相应操作的数据元素集合。它包含三方面的内容,逻辑关系,存储关系及操作。
不同种类的数据结构适合于不同种类的应用,而部分甚至专门用于特定的作业任务。例如,计算机网络依赖于路由表运作,B树高度适用于数据库的封装。
数据结构研究的内容:就是如何按一定的逻辑结构,把数据组织起来,并选择适当的存储表示方法把逻辑结构组织好的数据存储到计算机的存储器里。
os
模块是Python中用于与操作系统进行交互的标准库之一。它提供了许多函数来执行文件和目录管理,处理文件路径,以及与操作系统交互的其他功能。下面是对os
模块的一些主要功能的详解:
创建目录
os.mkdir(path)
: 创建单级目录。os.makedirs(path)
: 递归创建多级目录。删除目录
os.rmdir(path)
: 删除指定目录。os.removedirs(path)
: 递归删除目录,直到指定目录。文件和目录存在性检查
os.path.exists(path)
: 检查文件或目录是否存在。os.path.isfile(path)
: 检查给定路径是否是文件。os.path.isdir(path)
: 检查给定路径是否是目录。重命名和移动
os.rename(src, dst)
: 重命名文件或目录。os.replace(src, dst)
: 替换文件或目录,如果目标已经存在。列出目录内容
os.listdir(path)
: 返回目录中的所有文件和目录的列表。删除文件
os.remove(path)
: 删除指定文件。连接路径
os.path.join(path1, path2, ...)
: 将多个路径组合成一个路径。获取文件名和目录名
os.path.basename(path)
: 返回路径的基本名称(文件名或目录名)。os.path.dirname(path)
: 返回路径的目录部分。获取路径信息
os.path.abspath(path)
: 返回路径的绝对路径。os.path.split(path)
: 将路径拆分为目录和文件名的元组。os.path.splitext(path)
: 将路径拆分为文件名和扩展名的元组。检查路径属性
os.path.isabs(path)
: 检查路径是否是绝对路径。os.path.islink(path)
: 检查路径是否是符号链接。os.path.realpath(path)
: 返回符号链接的绝对路径。执行系统命令
os.system(command)
: 在系统上执行命令。获取环境变量
os.getenv(name)
: 获取环境变量的值。os.putenv(name, value)
: 设置环境变量的值。进程控制
os.getpid()
: 获取当前进程的PID。os.kill(pid, signal)
: 向指定PID的进程发送信号。文件描述符操作
os.open(file, flags[, mode])
: 打开文件并返回文件描述符。os.close(fd)
: 关闭文件描述符。这些只是os
模块中的一部分功能,但覆盖了许多常见的文件和目录操作,以及与操作系统进行交互的基本操作。
在Visual Studio Code中,c_cpp_properties.json
文件是用于配置C/C++扩展的解析设置的文件。在该文件中,excludePath
参数用于指定应该在解析期间排除的目录。以下是对excludePath
参数的详细解释:
1 | { |
${workspaceFolder}
: 这是一个变量,表示当前工作区的根目录。${workspaceFolder}/**
表示将包括工作区中的所有文件和子目录。
excludePath
数组: 用于指定要在解析期间排除的目录。可以指定一个或多个目录,并使用相对于${workspaceFolder}
的路径。在上面的示例中,两个目录都被排除了。
${workspaceFolder}/path/to/excluded_directory
: 表示要排除的第一个目录。${workspaceFolder}/another/excluded_directory/**/*.cpp
: 使用通配符**
表示所有子目录和其中的所有.cpp
文件都应该被排除。注意事项:
excludePath
时,确保使用正确的相对路径,并确保路径是以${workspaceFolder}
为基础的。**
来匹配任意目录或文件。在示例中,/**/*.cpp
表示匹配任意子目录下的所有.cpp
文件。通过使用excludePath
参数,你可以控制C/C++扩展在解析代码时忽略特定的目录,这对于排除不需要进行代码分析的目录非常有用。
在Visual Studio Code (VSCode) 中,launch.json
文件用于配置调试器的启动选项。当您在VSCode中使用C++进行调试时,可以使用 launch.json
文件设置环境变量以定制调试过程。
以下是如何在 launch.json
文件中设置环境变量的步骤:
打开 VSCode,并在您的 C++ 项目文件夹中找到或创建 launch.json
文件。通常,该文件位于 .vscode
文件夹中。
在 configurations
字段中添加一个调试配置。如果该字段为空,请复制以下 JSON 代码并粘贴到 launch.json
文件中:
1 | { |
environment
字段用于设置环境变量。您可以将需要的环境变量添加到该字段中。每个环境变量都以键值对的形式表示,键和值之间使用冒号分隔。例如,如果要设置名为 MY_ENV_VAR
的环境变量,可以添加如下配置:1 | "environment": [ |
保存 launch.json
文件。
在 VSCode 中打开您的 C++ 源代码文件,并在需要调试的行上设置断点。
单击 VSCode 左侧的调试图标(虫子图标),然后点击绿色的“启动调试”按钮。调试器将启动,并在设置的断点处停止。
如果有设置环境变量,它们将在调试过程中生效,您可以在调试过程中使用它们。
请注意:
launch.json
文件中设置环境变量。确保您使用的调试器支持此功能。launch.json
文件中设置的环境变量仅对该特定的调试配置生效。如果您有多个调试配置,每个配置可能需要不同的环境变量设置。以上步骤是为了在 VSCode 中通过 launch.json
文件设置 C++ 调试的环境变量。如果您在调试过程中遇到问题,请确保配置正确,并查看调试器的文档以获取更多帮助。
word wrap
首先,在官网找到需要下载的文件,点击下载,并将下载连接复制下来,例如:
https://az764295.vo.msecnd.net/stable/97dec172d3256f8ca4bfb2143f3f76b503ca0534/code_1.74.3-1673284829_amd64.deb
然后,将az764295.vo.msecnd.net
替换为vscode.cdn.azure.cn
,例如:
https://vscode.cdn.azure.cn/stable/97dec172d3256f8ca4bfb2143f3f76b503ca0534/code_1.74.3-1673284829_amd64.deb
这就是国内的镜像
背景:
方法:
code --no-sandbox --disable-gpu-sandbox --user-data-dir=".vscode-root"
VSCode 是什么,VS Code的全称是Visual Studio Code,但这全名实在是太长了,很多用户喜欢叫它VS Code。说起VS Code,官方定义它是一个免费的、开源的跨平台编辑器。之所以强调“编辑器”,我想是因为 VS Code 并无意成为一个全尺寸的集成开发环境,也就是IDE
很多人都把编辑器等同于IDE,其实从专业角度来讲并非这样。IDE 更为关注开箱即用的编程体验、对代码往往有很好的智能理解,同时侧重于工程项目,为代码调试、测试、工作流等都有图形化界面的支持,因此相对笨重,Java程序员常用的Eclipse定位就是IDE;而编辑器则相对更轻量,侧重于文件或者文件夹,语言和工作流的支持更丰富和自由,VS Code 把自己定位在编辑器这个方向上,但又不完全局限于此。
要理解VS Code代码编辑器的设计思路,就需要先看看VS Code的发展轨迹。
从我的角度看,不管你是学习编程语言,还是框架、编辑器,都应该先去看看它的来龙去脉,了解它们是怎么发展而来的,曾经遇到了什么问题,又是怎么解决的,这些信息都便于你从大局上提高对事情本质的认识
VSCode 发展历史:https://geek-docs.com/vscode/vscode-tutorials/what-is-vscode.html
简短地了解了 VS Code 的历史后,如果你也认同它的设计哲学和使命,你肯定还想知道该如何把 VS Code 的这一套转化为自己的内力。我在第一讲 “学编辑器,到底应该‘学’什么?” 里讲过编辑器学习的通用办法,在 VS Code 身上也是适用的。你可以按照以下三个步骤来逐步掌握 VS Code。
通过这三个步骤,你在使用 VS Code 时就能够“随心所欲”了。除此之外,我也建议你关注 VS Code 每月的发布更新日志,官方团队会详细讲解每个版本新增的功能。VS Code 的官方博客也非常值得订阅,团队成员会经常分享开发过程的心得感悟,算得上是最前沿的技术分享。
如果你是 Windows用户,安装并重启系统后,你就可以在命令行中使用 code 或者 code-insiders了,如果你希望立刻而不是等待重启后使用,可以将 VS Code 的安装目录添加到系统环境变量 PATH中, Windows 64 位下的 VS Code 安装路径是 C:\Program FIles\Microsoft VS Code下。
如果你希望使用已经打开的窗口来打开文件,可以在 code 命令后添加参数 -r来进行窗口的复用。
你也可以使用参数 -g <file:line[:character]>
打开文件,然后滚动到文件中某个特定的行和列,比如:
code -r -g package.json:128
命令,你就可以打开 package.json
这个文件,然后自动跳转到 128 行。VS Code 也可以用来比较两个文件的内容,你只需使用 -d参数,并传入两个文件路径,比如:
code -r -d a.txt b.txt
命令,就可以比较a.txt
和b.txt
两个文件的内容了。VS Code 命令行除了支持打开磁盘上的文件以外,也接受来自管道中的数据。这样你就可以将原本在命令行中展示的内容,实时地展示在 VS Code 里,然后在编辑器中搜索和修改。比如,你可以把当前目录下所有的文件名都展示在编辑器里,此时只需使用ls | code -
命令。
移动光标最常用的就是方向键,但是方向键每次只能把光标移动一个位置,可以说是一种相对低效的方式。
首先是针对单词的光标移动。这个你应该比较熟悉,绝大多数原生的编辑应用和文本框都支持。这也是我自己最常用的一组快捷键。
第二种方式是把光标移动到行首或者行末。比如第一行代码是 function foo() {,你只需按住 Cmd + 左方向键(Windows 上是 Home 键),就可以把光标移动到了这行的第一列;而如果你按住 Cmd 和右方向键(Windows 上是 End 键),光标就会被移动到 { 的后面。
接下来一种是对于代码块的光标移动。很多编程语言都使用花括号将代码块包裹起来,比如 if、for 语句等,你很可能会希望通过一个快捷键,就能实现在代码块的始末快速跳转。比如在这5行代码示例中,第一行到第三行代码是函数 foo 的定义,由一对花括号包裹起来,当你把光标放在花括号上时,只需按下 Cmd + Shift + \(Windows 上是 Ctrl + Shift + \
),就可以在这对花括号之间跳转。
最后一种基础的光标操作就是移动到文档的第一行或者最后一行,你只需按下 Cmd 和上下方向键即可(Windows 上是 Ctrl + Home/End
键)。
比如你想把当前行中光标之前的文本全部删除,就可以先选中这段文本(Windows/Linux: Home + Shift,macOS: Cmd + Left + Shift ),然后再按删除键。不过对于频繁使用的删除操作,你肯定希望单次操作就可以完成任务,而不是重复地选择文本然后删除,那么你需要记住下面几个命令。
假设你把光标放在第二行代码的中间位置,然后按下 Cmd 和 Backspace(MacOS上就是“fn + delete”的组合,Windows 上未绑定快捷键,可以打开命令面板运行“删除右侧所有内容”),就能够把第二行代码光标后(右侧)的字符全部删掉。
按下 Cmd 和 Delete 键则是删除当前行中光标前(左侧)的所有内容(Windows 上未绑定快捷键,可以打开命令面板运行“删除左侧所有内容”)
删除单词内的字符与此类似。假设把光标放在第一行第四个字符 c 的后面。Option 加左方向键把光标移动到 function 这个单词的开头,Option加左方向键再加 Shift 即可选中 func 这四个字符,而Option 加 Delete 则会删除 func 这四个字符。这里你可能看出来了,这些快捷键共同的是 Option 键,然后通过按下 Shift 或者 Delete 键,来达到不同的效果。
相反地,Option 加 Backspace(MacOS上就是“fn + delete”的组合) 则会删除 function 的后四个字符 tion。
前面我们提到,VS Code 内置了很多的命令,但是并没有为每个命令都提供一个快捷键,毕竟快捷键的组合总是有限的。不过 VS Code 提供了快捷键的修改和自定义功能,这样你就可以根据自己的使用习惯,给自己常用的命令指定顺手的快捷键。
首先你可以打开命令面板(你还记得它的快捷键不?),搜索“打开键盘快捷方式”然后执行,这时你将看到相对应的界面。
然后通过搜索找到你希望修改快捷键的命令,双击,接下来你只要按下你期望的快捷键,最后按下回车键就可以了。
比如,你可以搜索“选择括号内所有内容”,双击,按下”Cmd + Shift + ]”,然后按下回车,这个快捷键就绑定上了。
VS Code 的快捷键修改界面已经考虑到了这一点,你可以在搜索框内搜索你使用的快捷键,然后就可以看到这个快捷键当前对应的命令是哪个。
要删掉一行代码,你可以选中它,然后再按 Delete 键。不过还有一个快捷键,那就是直接按下 “ Cmd + Shift + K ” (Windows 上是 “Ctrl + Shift + K”),当前代码行就可以被删除了。
如果你只是想要剪切这行代码,那么你直接按下 “ Cmd + x ” (Windows 上是 “Ctrl + x”) 即可。
我想你肯定很清楚,“Enter” 键的基础作用是能在编辑器里光标所在的位置添加一个换行符。但是很多时候你可能并不是单纯地要将一行分成两段,而是希望在这行的下面或者上面开始一段新的代码。
这个功能对应的快捷键非常好记,它跟 “Enter”键十分接近。当你想在当前行的下面新开始一行时,你只需按下 “Cmd + Enter” (Windows 上是 “Ctrl + Enter”);而当你想在当前行的上面新开始一行时,你只要按下 “Cmd + Shift + Enter” (Windows 上是 “Ctrl + Shift + Enter”)就行了
当你想移动一段代码时,一般你可能会分三步走:先选中,再剪切,最后粘贴。不过我更喜欢的是按住 “Option + 上下方向键”(Windows中就是“Alt + 上下方向键”) ,将当前行,或者当前选中的几行代码,在编辑器里上下移动。
如果你同时按住 “Shift” 键的话,也就是 “Option + Shift + 上下方向键”(Windows中就是“Alt + shift + 上下方向键”),那就可以复制这几行,然后粘贴到当前行的上面或者下面。
另外,你在尝试“Option + 上下方向键”这个快捷键“上下移动”时,可能也发现了,当你把一段代码移动到花括号里面或者外面时,代码前的制表符或者空格的数量会自动发生改变,这样你就不需要移动完代码后再调整了。
Ctrl + U
),就可以撤销这一次光标的移动。VSCode 代码格式化快捷键,我们平常在做自己的小项目或者随便写一些脚本的时候,可能不会太在意代码的格式。不过一旦开始团队合作,整个项目组则会选择同一个代码风格和格式以有效降低协同成本。所以定期对自己写的代码进行格式化是个很好的习惯。
你可以按下 “Option + Shift + F” (Windows 上是 Alt + Shift + F
)来对整个文档进行格式化,VS Code 也会根据你当前的语言,选择相关的插件。当然,前提条件是你已经安装了相关插件。
你也可以选中一段代码,然后按下 “Cmd + K Cmd + F” (Windows 上是 Ctrl + K Ctrl + F),这样只有这段被选中的代码才会被格式化。
Ctrl + /
)。如果你需要把一整段代码注释掉,按下 Option + Shift + A即可。VS Code自动补全,VS Code 当中的自动补全内容,其实是由语言服务来提供的。本文介绍VS Code自动补全功能和VS Code自动补全设置。
VS Code 为编程语言工作者提供了统一的 API ,即 Language Server Protocol,每种语言都能够通过实现这个 API 在 VS Code 上得到类似 IDE 的开发体验,而各个语言根据这个 API 实现的服务,就被称为语言服务。
语言服务会根据当前的项目、当前的文件,以及光标所在的位置,为我们提供一个建议列表。这个列表包含了在当前光标位置下我们可能会输入的代码。当我们不断地输入字符,VS Code 就会根据当前输入的字符,在这个列表进行过滤。
如果我们偶尔觉得这个自动补全窗口是多余的,希望暂时不看到它,可以按下 Escape 键将其隐藏。后续如果希望再次看到这个窗口,除了通过打字来将其调出以外,我们还可以按下 “Ctrl + 空格键”
来手动地调出建议列表。
刚才我们提到,VS Code 会根据我们输入的字符在这个建议列表里进行过滤。同时,这个过滤是允许我们犯一点小错误的,比如打字特别快的时候少打一个字母,VS Code 也能处理这个情况。比如在下面的动图里,我想使用 console 里的 debug 函数,但是我只打了 db 两个字母,建议列表依然为我提供了 debug 这个选项。
上面的这几个窗口,它们都是通过我们输入的内容自动触发的,也就是说,编程语言决定了我们什么时候看到什么内容。虽然我们可以通过快捷键将其快速地关闭和唤出,但是有的时候自动补全窗口出现得过于频繁,也是会影响我们的编程体验的,毕竟悬浮窗口会遮盖一部分代码,影响我们的阅读。
不过,我们可以通过几个设置,控制自动补全窗口出现的频率和方式,甚至这个窗口的大小。
首先我们可以通过设置 “editor.quickSuggestions” 来决定在什么语境下自动补全窗口会被唤出。默认设置如下:
1 | "editor.quickSuggestions": { |
这时你可能会问了,如果关闭了这个设置,我想看到自动补全该怎么办呢?不用担心,当你按下 “Ctrl + 空格键” 之后,这个窗口依然会被打开,不管设置是关闭还是开启的状态。看到这个设置,你肯定也就明白了,为什么默认情况下你在写注释的时候没有代码自动补全的提示了吧。
参数预览窗口也是一样的,你可以通过参数 “editor.parameterHints.enabled” 将其关闭。当你觉得自己需要看一看参数预览时,按下快捷键或者通过命令面板就能够将其打开了。
上面的这个设置决定“是与否”的问题,但你也可以控制自动补全窗口出现的时间。自动补全窗口监听文件内容的变化,当你停止输入时,它就会试着给你提供建议。但是有的时候你打字稍微快一些,自动补全窗口才刚刚出现,你就输入了更多的内容,紧接着代码服务就要重新计算并提供建议了。如果你希望减少这种不必要的提示,可以增大设置 “editor.quickSuggestionsDelay” 的值,这样在你输入完代码后,自动补全窗口就会多等一会儿,然后再跳出来。
其他几个自动补全的设置,你可以在设置里搜一搜 “editor.suggest”,自己修改玩一玩。
上面提到的几个功能,它们都依托于语言服务来提供内容。但是有的时候,语言服务并不完美。编辑器于是提供了一种相对 “笨” 一些的提示,那就是基于单词的提示。编辑器通过分析当前的文件里的内容,进行简单的正则表达式匹配,给我们建议已经出现过的单词。
最简单的方式,也是我们每个人最熟悉的方式,就是按住鼠标左键,然后拖动鼠标,直到选中所有我们想要选择的文字为止,再松开鼠标即可。
那是不是说鼠标用户要完成类似的操作,就只能“一点、二拖、三松手”呢?当然不是,VS Code 其实给鼠标也配备了类似的快捷键。
在VS Code中:
到这里你可能会问,如果我想要使用鼠标,选中其中的多行代码该怎么办?VS Code也考虑到了这个情况,在编辑器的最左边,显示的是每一行的行号。如果你单击行号,就能够直接选中这一行。如果你在某个行号上按下鼠标,然后上下移动,则能够选中多行代码。
当我们想要修改一个函数或者变量的名字的时候,我们只需要把光标放到函数或者变量名上,然后按下F2,这样这个函数或者变量出现的地方就都会被修改
这个操作并不是一个粗暴的搜索关键词并替换,在上面的动图中你可以看到,最后一行代码里有个 bar3函数调用,但当我们去重命名 bar这个函数时,bar3并没有受到影响。
除了重命名外,另一个常用的重构的操作就是把一段长代码抽取出来转成一个单独的函数。在VS Code中,我们只需选中那段代码,点击黄色的灯泡图标,然后选择对应的重构操作即可。
要注意的是,并不是每个语言服务都支持重构的操作。如果你选中一段代码后,但没有看到那个黄色的灯泡图标,那么也就是说你使用的这门语言可能还没有支持快速重构。
VS Code文本编辑,在 VS Code中,我们除了能够使用鼠标来选择文本以外,还能够使用鼠标对文本进行一定程度的修改,我们把它称为拖放功能(drag and drop)。
比如在今天的示例代码中,我们选中 bar 这个函数,然后将鼠标移到这段选中的代码之上,按下鼠标左键不松开。这时你可以看到,鼠标指针已经从一条竖线,变成了一个箭头。这时候我们移动鼠标的话,就可以把这段文本拖拽到我们想要的位置。
在移动的过程当中,我们能够在编辑器中看到一个由虚线构成的光标,当我们松开鼠标左键的时候,这段文本就会被移动到这个虚拟的光标所在的位置。
如果我们在拖拽这段文本的同时,按下 Option 键(Windows 上是 Ctrl 键),鼠标指针上会多一个加号,这时候我们再移动鼠标或虚拟光标至我们想要的位置,然后当我们松开鼠标左键的时候,这段文本将会被复制粘贴到虚拟光标所在的位置,也就是我们既定的目标位置。
你看,在移动鼠标的过程中,多按了个 Option 键(Windows 上是 Ctrl 键),操作结果就由原来的“剪切+粘贴”变为“复制+粘贴”了。
VSCode 多光标特性,在我们的日常编码过程中,有很多工作,它本身就是具有“重复”属性的。比如你需要把多个单词的第一个字母从小写变成大写,这种跟业务逻辑相关的重复性操作,编辑器很难为它们一个个单独做优化。
而 VS Code 的多光标特性其实就是用来解决这类问题的。当你在一个文本框或者某个输入框里打入字符时,会有一个竖线来显示你将要输入文字的位置,这就是“光标”。顾名思义,多光标其实就是多个输入位置,这里你可以脑补下多个竖线的场景。
多光标特性允许你在输入框的多个位置创建光标,这样你就可以在多个不同的位置同时输入文字或者执行其他操作
“Cmd + D” 这个命令的作用是,第一次按下时,它会选中光标附近的单词;第二次按下时,它会找到这个单词第二次出现的位置,创建一个新的光标,并且选中它。这样只需要按下三次,你就选中了所有的“5”。这个时候你再按下 “右方向键”,输入“px”,即可完成任务。
接下来讲讲第二种,是跟代码行批量处理有关,也还是用的前面的代码。首先你选择多行代码,然后按下 “Option + Shift + i” (Windows 上是 Alt + Shift + i),这样操作的结果是:每一行的最后都会创建一个新的光标。
不过,VS Code 中还有一个更加便捷的鼠标创建多光标的方式。当然,这首先要求你的鼠标拥有中键。你只需按下鼠标中键,然后对着一段文档拖出一个框,在这个框中的代码就都被选中了,而且每一行被选中的代码,都拥有一个独立的光标。
VS Code符号跳转,文件跳转和行跳转,是代码跳转的基本操作,也是日常编码中的高频操作。不过有的时候,你可能会希望能够立刻跳转到文件里的类定义,或者函数定义的位置。为了支持这种跳转,VS Code 提供了一套 API 给语言服务插件,它们可以分析代码,告诉 VS Code 项目或者文件里有哪些类、哪些函数或者标识符(我们把这些统称为符号)。
如果要在一个文件里的符号之间跳转,你只需按下 “Cmd + Shift + O” (Windows 上是 Ctrl + Shift + O),就能够看到当前文件里的所有符号。
使用方向键,或者搜索,找到你想要的符号后,按下回车,就能够立刻跳转到那个符号的位置。如下图所示:通过符号功能跳转到指定的代码位置
请注意,在按下 “Cmd + Shift +O”后,输入框里有一个 “@”符号,这个符号在这里的意义,我会在后面的章节里去介绍,你可以先留个心眼。这时,如果你输入 “:”,就可以将当前文件的所有符号,进行分类,这样搜索符号也就更加方便。
有些语言除了提供单个文件里的符号,还支持在多个文件里进行符号跳转。比如在 VS Code 里,如果你打开了多个 JavaScript 文件,就可以按下 “Cmd + T” (Windows 上是 Ctrl + T),搜索这些文件里的符号。
通过“Cmd + T”,搜索多个文件的符号
VS Code引用跳转,很多时候,除了要知道一个函数或者类的定义和实现以外,你可能还希望知道它们被谁引用了,以及在哪里被引用了。这时你只需要将光标移动到函数或者类上面,然后按下 “Shift + F12”,VS Code 就会打开一个引用列表和一个内嵌的编辑器。在这个引用列表里,你选中某个引用,VS Code 就会把这个引用附近的代码展示在这个内嵌的编辑器里。
Shift+ F12打开函数引用预览
VSCode代码片段,有的时候,我们经常输入的代码是业务强相关的,语言服务没法做出优化;或者是一些我们经常使用的定式,比如循环语句、创建一个新的类或者一个 UI 控件,我们经常写类似的代码,只不过每次都要做细微的修改。对于这些代码,我们可以将它们抽象成模板,保存起来,等下次要使用的时候直接调用即可。
代码片段是对常用代码的一个抽象,它保留了大部分不变的代码,然后把需要经常变动的部分,换成变量,这样等下次调用它的时候,只需要把这些变量换成我们需要的就可以了
首先,我们打开命令面板,搜索“配置用户代码片段”(Configure User Snippets)并且执行。这时候我们会看到一个列表,让我们选择语言。这里我们依然选择 JavaScript 作为我们的示例语言,不用担心,代码都是非常简单和易于理解的。命令面板,搜索“配置用户代码片段”并且执行
选择完语言后,我们就能看到一个 JSON 文件被打开了,这个文件里的内容,现在都是被注释掉的。我们可以选中第七行到第十四行,按下 Cmd+ / 取消注释。
在上面的例子里,这个代码片段的名字叫做 Print to console 。这个代码片段对象的值,也就是花括号里的代码,必须要包含 “prefix” 前缀和 “body” 内容这两个属性。同时,这个值还可以包含 “description” 描述这个属性,但这个属性不是必须的。
“prefix” 的作用是,当我们在编辑器里打出跟 “prefix” 一样的字符时,我们就能在建议列表里看到这个代码片段的选项,然后我们按下 Tab 键,就能够将这个代码片段的 “body” 里面的内容插入到编辑器里。如果这个代码片段有 “description” 这个属性的话,那么我们还能够在建议列表的快速查看窗口里看到这段 “description”。
输入 log 即可看到 Print to console 代码片段,然后再按下回车或者 Tab 键,就能够将这个代码片段插入编辑器了。
VSCode折叠代码快捷键,我们再来一起看一下有哪些折叠和展开代码的快捷键。首先是折叠和展开代码的两个快捷键。
当我们按下 “Cmd + Option + 左方括号”(Windows 上是 Ctrl + Shift + 左方括号),当前光标所处的最内层的、可以被折叠的代码就会被折叠起来。请注意,我们在这里加了两个限制条件,“最内层”和“可以被折叠”。我们可以先用下面一个小例子来理解这两个条件。
如果你是在一个比较大的屏幕上工作,需要快速了解整个文件的全貌,并且还能靠鼠标快速地移动,那么这时小地图就很有用了。这个功能默认是打开的,所以你无需特别设置。这个使用起来比较简单,你可以像我在图中展示的那样试着打开一个较大的文件,感受一下它的妙处。
很多游戏中也有类似的小地图功能,不知道你有没有似曾相识的感觉。
除了控制小地图是否打开,编辑器还为我们提供了几个渲染的配置项。比如说,默认情况下,小地图会将每个字符都渲染出来。但是我们并不能真正地通过小地图来看代码,我们只是要看个大概结构罢了,那么我们可以打开命令面板,搜索“打开设置”(Open Settings),进入设置界面后,搜索 “editor.minimap.renderCharacters” ,找到后将其关闭,这样一来,所有的字符,都会被渲染成一个个小色块。
同样的,我们还可以通过 “editor.minimap.maxColumn” 来控制小地图里每一行渲染多少个字符。很多时候我们只需看下每行代码前的缩进和前面的代码高亮,就能看出个大概来了。
VSCode单文件搜索,今天我们重新回到原点,来看一下如何使用编辑器自带的文本搜索功能,快速地穿梭于海量的代码之中。在我看来,一个功能丰富且快速的搜索,在很多情况下甚至会比语言服务还要来得有用。
我们把光标放在编辑器当中,然后按下 “Cmd + F” (Windows 上是 Ctrl + F),就能够快速地调出搜索窗口(可能这个命令你早就发现了或者经常使用了)。当我们调出搜索窗口的时候,编辑器就会把当前光标所在位置的单词自动填充到搜索框中。与此同时,当前文件里和搜索关键词相同的单词都会被高亮出来。
自动填充搜索关键词的好处在于,当我们按下 “Cmd +F” 搜索这个单词之后,我们还能够立刻通过回车键或者 “shift+回车键” 在所有搜索结果当中快速跳转。
这里需要注意的事情是,当我们开始搜索的时候,光标已经被移动到了搜索框当中,如果在这时候我们继续打字的话,那原有的搜索关键词将会被修改。
如果我们希望找到搜索结果后,接下来就直接修改编辑器中的内容,那么就得将光标重新移动到编辑器当中,听起来就挺不方便的,是不是?
这种情况下,我们不妨换一个快捷键。首先我们将光标移动到我们想要搜索的单词处,然后按下 “Cmd + G” (Windows 上是 F3),此时我们同样调出了搜索框,但与前面 “Cmd +F ” 这个快捷键不同的是,这时光标依然是在编辑器当中,而不是在搜索框中。
下面我们再一起来看下这个搜索框中都有哪些功能。
当我们在搜索框中打字的时候,搜索操作是自动触发的,而无需我们再按下回车键去手动地执行搜索这个操作。
除了搜索纯文本以外,搜索框还支持多种不同的搜索方式。比如,在搜索框的最右侧,就有三个配置按钮。
这三个功能的快捷键的配置,相信你已经看出其中的诀窍了,它们分别使用了 Case、Word 和 Regular Expression 的第一个字母作为快捷键的一部分,若你知道是这几个单词,那相信对应的快捷键你就不会容易忘了。
我们可以先选中一段文本,然后按下 “Cmd + F” 调出搜索框,这之后点击这个按钮,就可以将这段文本的范围设置为接下来的搜索区域。然后当我们在输入框里输入关键字后,编辑器就只会在这个区域里进行搜索。
上面我们提到的功能,都是 VS Code 的默认行为。但也有部分用户不喜欢搜索框的一部分行为,比如说自动填充搜索关键词。那你可以打开设置,搜索 “editor.find.seedSearchStringFromSelection” 来关闭它。
也有个别用户觉得,如果选中了多行文本,那么当开始搜索时,应该自动地只在这几行代码里进行搜索。要达成这样的目的,你则需要打开设置 “editor.find.autoFindInSelection” 。
多文件搜索的运行方法跟单文件搜索非常类似。单文件搜索,我们是通过按下“Cmd+ F” 来调出搜索窗口的,而多文件搜索则是通过按下 “Cmd + Shift + F” (Windows 上是 Ctrl + Shift + F)来调出多文件搜索的视图。
默认情况下,当我们调出多文件搜索的视图时,VS Code 会在当前打开的文件夹下进行搜索。不过,要发挥多文件搜索的更大功效,我们可以通过书写配置来决定在哪些子文件夹下进行搜索,以及过滤掉哪些特殊的文件或者文件夹。
要完成这样的配置,我们需要点击搜索框下三个点形状的图标,点开后,我们能看到两个输入框,它们的名字分别是“包含的文件” 和 “排除的文件”。这两个配置的书写格式是 glob,很多编程语言和配置都会使用 glob 来模糊匹配文件名和文件夹,估计你已经有所了解。而如果你不熟悉的话,就当作是课后作业了,这一定不是你最后一次需要书写 glob。
第一个是 “search.collapseResults” 。它是用来控制是否自动展开搜索结果。默认的配置是 “auto” 自动, 也就是说,VS Code 会根据搜索结果的多少来决定是否要将某个文件下的搜索结果展开,如果某个文件夹下的结果过多的话,就会将其暂时折叠,用户需要展开结果。我自己喜欢将其设置为 “alwaysExpand”,这样我每次都能直接看到结果了。
第二个是 “search.location” ,也就是多文件搜索视图的位置。默认情况下,搜索视图会出现在侧边栏。但是 VS Code 同样允许你把搜索视图放到底部面板中去,你只需将其修改为 “panel” 即可。相信很多用户都跟我一样,使用过非常多把搜索视图放在底部的开发工具,并且很习惯了,那这个设置就能够帮助到我们。
编辑器会根据你指定的制表符的长度,来决定缩进参考线的位置。这样你就可以非常清楚地知道代码有没有正确地缩进,而且也方便你区分出不同代码块之间的层级关系。这个功能是可以通过 editor.renderIndentGuides 来控制开关的。
而图2中的竖线则不一样了,它叫做垂直标尺。如果你的项目中有规定说每一行代码不得超过多少个字符,比如说120个字符,那么你就可以将标尺设置为 120,即 editor.rulers: [120]。这样的话编辑器就会在第120个字符所在的位置处画出这样一条垂直的竖线,所以你一眼就可以看出自己的代码是否达标。
VS Code是如何管理文件和文件夹,首先需要说明的是,VS Code 的各个功能,都是基于当前打开的文件或者文件夹的。
该怎么去理解这个概念呢?
VS Code 则选择了一种相对轻量,而且大家都易于理解的方式,那就是所有的操作都基于文件和文件夹。当你打开一个文件夹,VS Code 的核心功能就会对这个文件夹进行分析,并提供对应的功能。比如,在打开的文件夹下检测到有 .git 文件,就加载 Git 插件来提供版本管理的功能;或者发现文件夹下有 tsconfig.json ,就会激活 TypeScript 插件提供语言服务
当你第一次打开 VS Code 的时候,工作台中还没有打开任何文件夹。这时候在欢迎界面的左上方,你能够看到:“新建文件”和“打开文件夹”等这样的快捷键。
未打开文件夹,状态栏为紫色
这时候请注意工作台最下方的状态栏,当 VS Code 没有打开任何文件夹的时候,它的颜色是紫色的。而如果在工作台中打开了某个文件夹,状态栏的颜色就会变成蓝色。
VS Code 多文件夹工作区,多文件夹工作区(multi-root workspace)。老实说呢,这个概念是有一定的理解难度的。
上面我们提到的基于文件夹的这种项目管理方式,从 VS Code 第一天开始就存在了。也几乎从第一天开始,我们就收到了用户对于这一个设计不满的反馈。对于这些不满的用户而言,他们的痛点在于他们经常需要同时对多个文件夹下的代码进行操作。但是 VS Code 关于单个文件夹的这种操作模式,要求了他们必须同时打开多个窗口,并不停地在它们之间切换。
多文件夹工作区就是为了针对这个问题而实现的解决方案。那下面我们就一起来看一看怎样去创建一个多文件夹工作区。
首先,在 VS Code 中打开一个文件夹,此时 VS Code 处于一个单文件夹的状态。然后你可以调出命令面板,搜索 “将文件夹添加到工作区” (add folder to workspace)并执行,或者使用菜单,“文件 —> 将文件夹添加到工作区”,这之后,选择你想要在当前窗口打开的文件夹。
此时在资源管理器里的标题栏里,你能看到“无标题 (工作区)”这样的文字,这说明当前的工作区已经有多个文件夹了,只是现在你还没有保存这个多文件工作区,也没有给它指定一个名字。
要保存这个工作区,接下来你可以调出命令面板,搜索“将工作区另存为” (save workspace as),VS Code 就会为这个工作区创建一个文件,这个文件的后缀名是 “code-workspace”。比如,在下面的动图中,我给这个工作区取名为 sample,然后指定在 Code中这个文件夹下保存。这样操作后,VS Code 就会在 Code 文件夹下创建一个 sample.code-workspace 文件。
你可以看到,操作完之后资源管理器的标题栏已经相应地改变了。另外,sample.code-workspace 虽然有个特殊的后缀,但这个文件的格式其实也是 JSON,你可以自行打开这个文件查看一下。
这个 JSON 文件,默认有两个键(key)。第一个是 folders 文件夹,它里面罗列的是这个多文件工作区里有哪些文件夹。可以看出,这些文件夹的地址,都是这个 sample.code-workspace 文件的相对路径。第二个则是 settings 设置,你可以在这个值里面添加专属于这个多文件夹工作区的设置。它的作用,跟上面我们介绍的 .vscode 文件夹下的 settings.json 文件是类似的。
VSCode 代码调试器,和语言功能一样,VS Code 是把调试功能的最终实现交给插件来完成的。VS Code 提供了一套通用的图形界面和交互方式,比如怎么创建断点、如何添加条件断点、如何查看当前调试状态下参数的值,等等。无论你使用哪个编程语言或者调试器,这一套交互流程都是相似的。
而对于插件作者而言,他们需要完成的是如何把真正的调试工作跟 VS Code 的界面和交互结合起来,为此 VS Code 为插件作者提供了一套统一的接口,叫做Debug Adapter Protocol(DAP)。当用户在界面上完成一系列调试相关的操作时,VS Code 则通过 DAP 唤起调试插件,由插件完成最终的操作。
VS Code 中有一个专门的用于管理调试功能的视图。我们可以点击界面左侧“昆虫”(也就是 bug 啦)形状的按钮,或者按下 “Cmd + Shift + D” (Windows 上是 Ctrl + Shift + D)来唤出调试视图。
在视图的最上侧,有个绿色的箭头按钮。这个按钮是用于启动调试器的。但是在上面的截图里,你可以看到在绿色箭头的右侧写着 “没有配置”。这说明现在 VS Code 还不知道该使用什么调试器来调试当前的代码。此时点击这个按钮或者按下 F5,我们能够看到一个列表。
首先,我们将鼠标移动到第五行代码的行号前面,点击鼠标左键,我们能够看到一个红色的圆点被创建了出来,这就是断点。当然,我们也可以把光标移动到第五行,然后按下 F9,同样可以在第五行创建断点。
此时,当我们再次点击调试视图上面的绿色箭头按钮,或者按下 F5,启动调试器,并且选择 Node.js ,VS Code 就会进入调试模式。
VSCode 代码调试器配置launch.json介绍,在调试视图的最上方,我们能够看到一个齿轮形状的按钮,它可以用于创建和修改 launch.json 文件。由于当前文件夹下没有 launch.json 文件,所以这个按钮的右上角有个红色的点,它告诉我们当前的调试配置有一点问题,让我们点击这个按钮。
这个 JSON 文件里的 configurations 的值就是当前文件夹下所有的配置了。现在我们只有一个调试配置,它有四个属性:
下面我们把 program 的值改为 ${workspaceFolder}/index.js,其中${workspaceFolder} 是代表当前工作区文件夹地址的预定义参数,使用它就能够准确地定位当前工作区里 index.js 文件了。(关于在配置文件里可以使用的预定义参数,请参考Visual Studio Code Variables Reference。 https://code.visualstudio.com/docs/editor/variables-reference
)
通用属性
虽然每个调试器各自控制着用户可以使用哪些属性,但是调试器之间还是有很多相同的地方,调试插件在很多时候都会使用相同的属性名来代表同样的功能。比如,我自己就是 Ruby 插件的作者,我在实现 Ruby 调试插件的时候,参考了很多 Node.js 和 PHP 调试插件对于属性的命名和使用。我在书写不同语言的调试配置时,经常使用的有下面这些:
GitLens
VS Code中的 Git 体验在易用性和完整性之间取得了一个不错的平衡,大部分用户都能够使用它完成工作,同时又不会被太多的功能吓到。但是很多硬核的 Git 用户肯定会觉得功能还不够用。包括但不限于:
RemoteHub
GitLens 作者 Eric Amodio 又出一款力作——RemoteHub。安装这个插件后,当你想在本地看某个 GitHub repository的代码时,你就不需要将代码 clone 下来了,你可以直接打开这个 repository 相关的工作区,所有文件、文件夹都是从 GitHub 按需下载下来。如果你连接 GitHub 的网速不错的话,那么使用体验可是比 GitHub 网站要好得多。
GitHub Pull Request
除了 Git 支持以外,一个呼声一直非常高的需求,就是在 VS Code中查看和审核 GitHub 上的 Pull Request。好消息是,VS Code团队和 GitHub 的 Editor Tools 团队一起合作,为我们提供了 GitHub Pull Request这个插件。
Settings Sync
如何在不同设备之间同步个人设置?VS Code自己并没有提供设置的同步,但通过 Settings Sync这个插件,你可以将个人设置同步到 Gist 中。
不过值得注意的是,虽然你的设置是同步到自己私人的 Gist 中,但是如果你的设置中有一些隐私信息,像密码、Token 之类的,还是不要使用此插件比较好。
Project Manager
我们在工作台的部分,介绍过 VS Code支持多文件夹工作区(multi-root workspace),以及如何通过快捷键在不同的项目之间来回切换。如果你不喜欢 VS Code默认的方式,那么你也可以试试 Project Manager。Project Manager 甚至还有一个专门的视图来展示所有的项目,非常方便。
VIM
编辑器相关的插件中最厉害的应该就是 Vim 相关的插件了,VS Code提供了一个 API 保证了 Vim 插件能够被正确地实现。不过 Vim 插件并不只有一个,下载量最大的,也是我参与的就是 VSCodeVim,它对 Vim keybings 的覆盖程度非常高。另一个非常受大家欢迎的就是amVim,它的性能也非常不错。
Rainbow Brackets
不管你是不是写函数式语言,当你的代码中有比较多的花括号时,要保证它们对称可以说是非常困难了。Rainbow Brackets这个插件,为同一对花括号指定一个单独的配色,这样你就能够轻松地一眼看出花括号的配对了。
Indent Rainbow
上面的 Rainbow brackets 是给花括号加上多种颜色,而 Indent Rainbow则是为你的代码缩进提供颜色上的提示:
这两个插件有异曲同工之妙,当然我还是建议写代码的时候,不要有太多的层级。
Pigment
既然说到颜色,就不得不提Pigment 这个插件。在介绍择色器(Color Picker)的时候我介绍过,VS Code会在每个颜色前面加上一个方块,用方块来展示代码所对应的颜色。Pigment 则是将颜色渲染在这段代码的下面,我自己还是蛮喜欢这种方式的。
Import Cost
JavaScript 经常被吐槽的一个地方,就是大家对 npm 库的使用程度非常高,经常为了一个简单的功能,引入了几兆甚至十几兆的 npm 包。Import Cost这个插件,很好地在代码中给我们以提示,告诉我们引入的某个包,它最终会导致整个项目的大小增加多少。
Rest Client
我们使用 REST API 的时候,经常需要发送一些样例数据对 API 进行测试,这时我们可以使用 Postman 这类的独立应用,也可以在 VS Code中使用 Rest Client插件,直接在编辑器里发送 REST 请求。
Code Runner
macOS 用户对 Code Runner 这个应用一定非常熟悉了,你可以使用 Code Runner 快速地书写代码并且执行,而无需设置环境配置工程之类的。VS Code里也有这样的插件,如果你有类似的需求,可以试一试。
Live Share
Live Share是微软官方出品的非常强大的服务,通过 Live Share service,你可以将你本地的工作区,直接分享给你的同伴,然后你的同伴就可以直接编辑你的代码,与你共享代码调试、集成终端等等,而无需安装任何环境。Atom 也有类似的服务叫做 Teletype。我工作中每次要和同事 Pair Programming 的时候,就会使用 Live Share。
同时 Live Share 服务还支持语音通讯,不过需要安装另一个插件 Live Share Audio。
当然有!你可以通过在项目的 .vscode 文件夹下,创建一个文件 extensions.json。你很熟悉了,这又是一个 JSON 文件,在这个 JSON 文件里,你只需提供一个键(key) recommendations,然后将你想要推荐给这个项目的其他工程师的插件的 ID 们,全部放入到这个数组中。当他们打开这个项目,而且并没有安装这些插件时,VS Code就会给他们提示了。
除了在 .vscode/extensions.json 文件推荐插件,如果你在使用多文件夹工作区(multi-root workspace),也可以在多文件夹工作区的配置文件里添加如下的设置:
task.json
launch.json
c_cpp_properties.json
launch.json
调试文件和task.json
任务文件中是支持变量替换的,这就意味着可以很方便的使用VScode一些预定以的变量。${variableName}
${workspaceFolder}
: 项目文件夹在VScode
中打开的路径${file}
: 当前打开的文件${relativeFile}
: 相对于${workspaceFolder}
的文件路径${fileBasename}
: 当前打开文件的名称${fileBasenameNoExtension}
: 当前打开文件的名称,不带扩展名${fileExtname}
: 当前打开文件的扩展名${fileDirname}
: 当前打开文件的文件夹名称Logpoints
true
时才会进行断点shift + F9
ctrl + p
: 快速搜索文件并跳转,添加:
可以跳转到指定行alt + 鼠标左键
: 选中多行同时编辑在 Visual Studio Code 中,如果你希望将焦点从编辑器切换到左侧的侧边栏(也称为 Activity Bar),可以使用以下方法:
使用键盘快捷键:
Ctrl + 0
(Windows/Linux)或者 Cmd + 0
(Mac)可以将焦点从编辑器切换到侧边栏的第一个图标。Ctrl + 1
、Ctrl + 2
、Ctrl + 3
等数字键(Windows/Linux)或者 Cmd + 1
、Cmd + 2
、Cmd + 3
等数字键(Mac)可以将焦点切换到侧边栏的不同图标。使用鼠标:
这些方法可以帮助你快速地将焦点从编辑器切换到左侧的工具栏,以便访问不同的功能和视图。
在 Visual Studio Code 中,你可以使用以下快捷键来实现分屏显示和切换:
分屏显示:
Ctrl + \
(Windows/Linux)或者 Cmd + \
(Mac)来进行分屏显示。这会在当前编辑器的右侧打开一个新的编辑器。切换焦点:
Ctrl + 1
、Ctrl + 2
等数字键(Windows/Linux)或者 Cmd + 1
、Cmd + 2
等数字键(Mac)来切换到不同的编辑器。Ctrl + \
(Windows/Linux)或者 Cmd + \
(Mac)来切换焦点到分屏的另一个编辑器。关闭分屏:
重新分屏:
Ctrl + \
(Windows/Linux)或者 Cmd + \
(Mac)来重新分屏。通过这些快捷键,你可以方便地在 Visual Studio Code 中进行分屏显示和切换。
Asio库相关的理论基础知识
Asio库是仅包含头文件的库
Boost.Asio 是一个非常流行的 C++ 库,用于实现异步 I/O 操作和网络编程。它最初作为 Boost C++ 库的一部分,但后来成为 C++ 标准库的一部分(自 C++11 起)。因此,Boost.Asio 的某些版本也包含在 Boost 库中。
独立版本的 Boost.Asio 是指可单独使用、独立于 Boost 库的版本。它通常是从 Boost 库中分离出来的、具有更轻量级的库。这样的版本可以更容易地集成到项目中,而无需包含整个 Boost 库。
独立版本的 Boost.Asio 通常具有以下特点:
Boost.Asio 独立版本的详细内容和特性与原始的 Boost.Asio 库非常相似,主要提供异步 I/O、TCP、UDP、定时器和网络编程相关的功能。它仍然支持异步事件和异步操作,提供了用于管理 I/O 对象、定时器和网络通信的类和函数。
要使用独立版本的 Boost.Asio,你可以从官方的 GitHub 仓库或下载页获取源代码,并按照提供的指南进行构建和集成。通常,独立版本的 Boost.Asio 具有更加现代化和改进的特性,因为它们可能是从较新版本的 Boost 库中提取出来的。
请注意,独立版本的 Boost.Asio 可能会有所不同,具体取决于版本和发布的时间。因此,建议查看官方文档和版本说明以获取特定版本的详细信息和使用说明。
asio::io_context
是 Boost.Asio 库(也是 C++ 标准库中的一部分,自 C++17 起)中的核心类之一。它是实现异步 I/O 操作的关键部分,用于驱动异步事件处理。
io_context
对象是异步操作的执行上下文,用于管理异步操作、事件处理、任务队列和事件循环。io_context
,可以注册异步操作(如套接字操作、定时器事件等),io_context
将在合适的时机进行调度、执行和完成这些异步操作。run()
: 开始 io_context
上的事件循环,处理已注册的所有异步操作,直到所有操作完成或 io_context
被停止。stop()
: 停止 io_context
上的事件循环。停止后,run()
函数将在处理完当前已注册的操作后立即返回。poll()
: 执行 io_context
上的事件循环,但仅处理当前可立即完成的操作,然后立即返回。restart()
: 重新启动已经停止的 io_context
。1 | #include <iostream> |
在上述示例中,io_context
用于驱动异步操作(这里是一个定时器异步等待)。通过调用 run()
方法,io_context
开始处理已注册的异步操作,并在完成所有操作或者遇到停止指令时返回。
io_context
是 Boost.Asio 中非常重要的一个类,它为异步操作提供了执行环境,能够有效地管理和调度异步事件,是异步编程的核心。
asio::thread_pool
是 Boost.Asio 库中的一个类,它提供了一个线程池,用于管理和执行异步操作。线程池是一种用于管理线程的技术,它可以预先创建一组线程,以便在需要时执行任务或处理异步操作。
asio::thread_pool
提供了线程池,可用于执行异步操作,避免了频繁创建和销毁线程的开销。asio::thread_pool(size_t num_threads)
构造函数: 创建具有指定数量线程的线程池。~thread_pool()
析构函数: 销毁线程池,等待所有线程执行完毕并释放资源。submit(Function && function)
: 提交任务到线程池,执行 function
函数。stop()
: 停止线程池,不再接受新的任务,等待所有任务执行完毕后销毁线程池。join()
: 阻塞等待线程池中的所有任务执行完成。notify_one()
和 notify_all()
: 用于唤醒正在等待的线程。1 | #include <iostream> |
在上述示例中,创建了一个具有 4 个线程的线程池 pool
,然后向线程池提交了 8 个任务。这些任务会被线程池中的线程异步执行。最后,调用 pool.join()
阻塞等待所有任务执行完成。
asio::thread_pool
提供了一种有效地管理和执行异步操作的方式,避免了线程频繁创建和销毁的开销,并提高了异步操作的执行效率。
asio::ip::tcp::socket
是 Boost.Asio 库中用于 TCP 协议的套接字类,用于在 C++ 中进行 TCP 网络通信。
asio::ip::tcp::socket
允许 C++ 应用程序创建 TCP 客户端或服务器套接字,并进行数据传输。constructor
构造函数: 创建 TCP 套接字。open()
: 打开套接字。close()
: 关闭套接字。connect()
: 用于客户端,连接到远程服务器。async_connect()
: 异步连接到远程服务器。bind()
: 将套接字与本地端口或地址绑定。async_bind()
: 异步绑定套接字。listen()
: 在服务器上监听传入连接请求。accept()
: 接受传入的连接请求。async_accept()
: 异步接受传入的连接请求。read_some()
和 write_some()
: 同步读取和写入数据。async_read_some()
和 async_write_some()
: 异步读取和写入数据。shutdown()
: 关闭套接字的输入、输出或全部流。下面是一个简化的 Boost.Asio TCP 服务器端示例,展示了如何使用 asio::ip::tcp::socket
接受连接和读取数据:
1 | #include <iostream> |
asio::ip::tcp::socket
是 Boost.Asio 中用于 TCP 通信的关键类之一,提供了处理 TCP 套接字的方法和功能,可以用于创建 TCP 客户端或服务器,并进行数据的读写操作。
asio::steady_timer
是 Boost.Asio 库中的一个定时器类,用于在指定时间点执行或触发操作。
asio::steady_timer
用于创建定时器对象,可以在设定的时间点之后触发回调函数。constructor
构造函数: 创建定时器对象。expires_at()
和 expires_from_now()
: 分别设置定时器的到期时间和到期时刻的相对偏移量。async_wait()
: 异步等待定时器触发。可以向定时器对象提交一个回调函数,在指定时间点触发回调。cancel()
: 取消定时器,终止尚未触发的操作。wait()
: 阻塞等待定时器触发。下面是一个简单的 Boost.Asio 定时器示例,演示了 asio::steady_timer
的基本用法:
1 | #include <iostream> |
在上述示例中,创建了一个 asio::steady_timer
对象 timer
,设置定时器在 5 秒后触发。然后使用 timer.async_wait()
异步等待定时器的触发,并指定了一个回调函数 timer_handler
。最后,调用 io_context.run()
运行事件循环,等待定时器触发并执行回调函数。
asio::steady_timer
类是 Boost.Asio 中用于管理定时器的重要类之一,允许程序在指定的时间点执行特定操作,通常用于实现定时任务、超时控制等功能。
在 Boost.Asio 中,asio::chrono::seconds()
函数是用于创建时间持续时间(duration
)对象的函数,表示以秒为单位的时间段。
这个函数位于 Boost.Asio 的时间相关命名空间中,asio::chrono
,用于创建与时间相关的持续时间对象,其中包括 std::chrono::duration
的各种变种。
1 | #include <iostream> |
在上述示例中,asio::chrono::seconds(5)
创建了一个表示 5 秒的时间段,然后将该时间段传递给 boost::asio::steady_timer
的构造函数,用于设置定时器在 5 秒后触发。
此函数的作用在于以秒为单位创建时间段,可以用于设置定时器、指定等待时间等场景。 Boost.Asio 中的这些时间函数通常是与异步操作和定时器相关的,使得在异步编程中方便地创建和管理时间段。
asio::steady_timer::async_wait()
是 Boost.Asio 中 steady_timer
类的成员函数,用于异步等待定时器到期并触发回调函数。
1 | template <typename WaitHandler> |
WaitHandler
:一个可调用对象,用于处理定时器到期时触发的回调函数。可以是函数指针、函数对象、lambda 函数等。async_wait()
函数安排一个异步操作,在指定的定时器到期时执行回调操作。该函数不会阻塞当前线程,而是在设置的时间段之后触发回调函数。
1 | #include <iostream> |
在上述示例中,async_wait()
函数用于异步等待定时器 timer
到期,并指定了一个名为 timer_handler
的回调函数处理定时器到期时的操作。io_context.run()
开始运行事件循环,等待定时器触发并执行回调函数。
该函数常用于异步编程中,用于设置定时器的到期事件,并在到期时执行相应的操作或回调函数。
asio::steady_timer::expires_at()
是 Boost.Asio 中 steady_timer
类的成员函数之一,用于设置定时器的到期时间点。
1 | template <typename TimePoint> |
TimePoint
:表示时间点的类型,通常为 std::chrono::time_point
,用于指定定时器的到期时间点。expires_at()
函数用于设置定时器 steady_timer
的到期时间点。当调用该函数并传递一个特定的时间点参数时,定时器将在指定的时间点触发,即执行定时器的回调函数或触发定时器到期事件。
1 | #include <iostream> |
在上述示例中,timer.expires_at()
用于设置定时器 timer
的到期时间点为当前时间加上 5 秒。随后使用 timer.async_wait()
异步等待定时器触发,在定时器到期时执行回调函数。最后,通过 io_context.run()
开始运行事件循环,等待定时器到期并执行回调函数。
expires_at()
函数对于预先设置定时器的到期时间非常有用,允许在稍后的时间点触发异步操作,使得在异步编程中更容易地控制定时器的触发时间。
在 Boost.Asio 中,asio::steady_timer::expiry()
是 steady_timer
类的成员函数,用于获取定时器的到期时间点。
1 | std::chrono::steady_clock::time_point expiry() const noexcept; |
expiry()
方法用于获取当前设置的定时器 steady_timer
的到期时间点。返回的是一个 std::chrono::steady_clock::time_point
对象,表示定时器将会到期的时间点。
1 | #include <iostream> |
在这个示例中,使用 timer.expires_at()
将定时器 timer
的到期时间点设置为当前时间加上 5 秒。然后调用 expiry()
方法获取定时器的到期时间点,并将其转换为 std::time_t
格式,最后使用 std::ctime()
打印定时器将会到期的时间点。
expiry()
方法对于需要了解定时器何时到期的情况非常有用,它允许程序员检查定时器当前的到期时间点,以便在需要时执行相应的操作。
在 Boost.Asio 中,asio::make_strand()
是一个用于创建 strand
对象的工厂函数。strand
提供了一种同步操作访问序列化(serialized)的方式,用于确保异步操作在多个线程中按照顺序执行,避免出现竞争条件。
1 | template <typename ExecutionContext> |
ExecutionContext
:表示执行上下文的类型,可以是 io_context
、strand
或其他支持的执行上下文类型。strand
对象。make_strand()
函数用于创建一个 strand
,它实际上是一个执行器(executor),可以确保在同一个 strand
内排队的操作按顺序执行,而不会发生竞争条件。
1 | #include <iostream> |
在这个示例中,make_strand()
创建了一个 strand
对象 strand
,然后使用 boost::asio::post()
将两个任务(lambda 函数)提交到 strand
内执行。由于这两个任务被提交到同一个 strand
中,它们会按照顺序在该 strand
中执行,避免了并发操作可能引发的竞争条件。
strand
对于需要序列化异步操作的情况非常有用,可以确保在一个特定的执行上下文中操作按顺序执行,增加了程序的可靠性和安全性。
在 Boost.Asio 中,asio::bind_executor()
是一个用于绑定执行上下文(executor)到处理器(handler)上的函数,它用于创建一个新的处理器对象,将给定的执行上下文绑定到现有的处理器上,从而确保处理器在指定的执行上下文中执行。
1 | template <typename Executor, typename Handler> |
Executor
:表示执行上下文的类型,例如 io_context
或 strand
。Handler
:表示处理器的类型,可以是函数对象、函数指针或者可调用对象。bind_executor()
函数用于创建一个新的处理器对象,它在调用原始处理器时,会确保使用提供的执行上下文(executor)进行执行。这样做可以确保处理器在指定的执行上下文中运行,从而实现异步操作的序列化和控制。
1 | #include <iostream> |
在这个示例中,asio::bind_executor()
函数将一个处理器对象(lambda 函数)与一个执行上下文(strand)绑定在一起。然后,通过调用返回的新处理器对象 handler
,可以确保该处理器在指定的 strand
中运行,从而保证了处理器的操作在该执行上下文中进行。这种绑定执行上下文到处理器的方式常用于确保异步操作的顺序执行或者将处理器绑定到特定的执行上下文中执行。
Boost C++ 库是一个非常强大的 C++ 库,提供了大量的功能和工具,包括智能指针、多线程、正则表达式、容器、图形学等。编译 Boost 库可能会有一些复杂性,因为 Boost 包含了大量的头文件和库,但下面是一个简要的教程,演示如何编译 Boost 库。
步骤 1:下载 Boost 库
首先,您需要下载 Boost 库的源代码。您可以从 Boost 官方网站(https://www.boost.org/)下载最新版本的 Boost 库。将源代码文件解压到您选择的目录中。
步骤 2:打开终端
在终端中导航到 Boost 库的源代码目录。您可以使用 cd
命令切换到该目录。
步骤 3:运行 Bootstrap 脚本
Boost 提供了一个名为 bootstrap.sh
(Linux/macOS)或 bootstrap.bat
(Windows)的脚本,用于配置编译过程。在终端中运行以下命令:
对于 Linux/macOS:
1 | ./bootstrap.sh |
对于 Windows:
1 | bootstrap.bat |
这将为您的系统配置 Boost 库的编译过程。
步骤 4:运行 b2 命令
接下来,您需要运行 b2
命令来编译 Boost 库。您可以使用以下命令:
1 | ./b2 |
这将默认编译所有 Boost 库的组件。如果您只需要特定的库,您可以在 b2
命令后面添加库名称,例如:
1 | ./b2 --prefix=/tmp/boost --with-filesystem --with-system |
这将仅编译文件系统和系统库。
步骤 5:等待编译完成
编译 Boost 库可能需要一些时间,具体取决于您的系统性能和所选的库。一旦编译完成,您将在 Boost 源代码目录中找到生成的库文件。
步骤 6:安装 Boost 库
您可以选择将编译后的库文件安装到系统目录中,以便其他项目可以轻松使用它们。运行以下命令:
1 | sudo ./b2 install |
这将把库文件复制到系统的默认位置。
注意:在 Windows 上,您可能需要使用 Visual Studio 编译工具来编译 Boost 库。您可以在 Boost 官方网站上找到有关使用 Visual Studio 的更多信息。
这是一个简要的 Boost 库编译教程。具体的步骤可能因您的系统和需求而有所不同。为了获得更详细的信息和特定于您的平台的说明,请查阅 Boost 文档或参考 Boost 官方网站上的编译指南。
通过调用find_package可以找到头文件和所需要的库文件或者是一个CMake打包配置文件
1 | find_package(Boost |
示例
1 | find_package(Boost 1.62.0 REQUIRED |
运行之后可以得到很多变量,下面列了一些主要的:
1 | Boost_FOUND - 如果找到了所需的库就设为true |
如果Boost库是自定义安装路径,可以在搜索package之前,通过设置一些变量来帮助boost库查找
1 | BOOST_ROOT - 首选的Boost安装路径 |
如果目标程序foo需要链接Boost库的regex和system,编写如下的CMakeist文件
1 | # CMakeLists.txt |
通过设置BOOST_ROOT来设置首选的搜索路径
通过MESSAGE函数把差找的结果都打印出来
Boost动态库链接。如果项目包含多个子模块,且子模块只用到顶层模块find_package找到的部分库,则用下述语句实现只链接子模块需要的Boost动态库
1 | target_link_libraries(foo Boost::regex) // 只使用regex |
Boost头文件库链接。在Boost库中有部分库只用头文件实现,并没有响应的动态库,若使用这部分库可以通过以下语句实现
1 | target_link_libraries(foo Boost::boost) |
Boost C++ 库包含了众多功能和组件,因此无法在一篇回答中详尽介绍所有。下面将展示一个使用 Boost 库的示例,涵盖智能指针、正则表达式和文件系统三个常用部分。请确保您已经成功编译了 Boost 库并将其包含在项目中。
1. 智能指针(Smart Pointers)示例:
智能指针帮助管理动态分配的内存,防止内存泄漏。以下是一个使用 Boost 智能指针的示例:
1 | #include <boost/shared_ptr.hpp> |
在上述示例中,我们使用了 boost::shared_ptr
来创建一个智能指针,它会自动管理整数的内存分配和释放。use_count()
函数用于获取引用计数。
2. 正则表达式示例:
Boost.Regex 提供了强大的正则表达式功能。以下是一个使用 Boost.Regex 的示例:
1 | #include <boost/regex.hpp> |
上述示例中,我们使用 boost::regex
创建了一个正则表达式,然后使用 boost::regex_search
检查字符串中是否包含匹配的文本。
3. 文件系统示例:
Boost 文件系统库提供了文件和目录操作功能。以下是一个使用 Boost 文件系统库的示例:
1 | #include <boost/filesystem.hpp> |
在上述示例中,我们使用 boost::filesystem::path
表示目录路径,并使用 boost::filesystem::exists
和 boost::filesystem::is_directory
函数来检查目录是否存在以及是否为目录。
这些示例涵盖了 Boost C++ 库的一小部分功能。要使用 Boost 的其他组件和功能,请查阅 Boost 官方文档,其中包含了详细的教程和示例代码,以帮助您更好地理解和应用 Boost 库的各个组件。
Boost C++ 库是一个非常受欢迎的开源 C++ 库集合,提供了各种功能和工具,用于增强 C++ 编程,包括数据结构、算法、多线程、正则表达式、智能指针、文件系统操作等。以下是 Boost C++ 库的一些主要组成部分和功能的详细介绍:
智能指针(Smart Pointers):Boost 提供了各种智能指针,如 shared_ptr
、unique_ptr
和 weak_ptr
,用于管理动态分配的内存,以避免内存泄漏和提高代码安全性。
容器和数据结构:Boost 包括许多增强的容器和数据结构,如 unordered_map
、unordered_set
、multi_index
、variant
和 any
,用于更有效地管理数据。
多线程支持:Boost 提供了一套多线程库,包括线程、锁、条件变量和原子操作,以便于编写并发程序。
正则表达式:Boost.Regex 提供了强大的正则表达式库,使您可以进行高级文本匹配和处理。
文件系统:Boost 文件系统库允许您进行文件和目录的操作,包括文件检查、复制、移动和删除。
日期时间和时间戳:Boost.Date_Time 库提供了日期、时间和时间戳处理的功能,可用于处理时间相关的任务。
图形学库:Boost.Graph 库用于图形算法和数据结构,支持图形遍历、搜索和分析。
泛型编程和元编程:Boost 具有强大的泛型编程和元编程工具,包括预处理器宏、类型萃取和模板元编程,用于创建通用、高效的代码。
库之间的交互性:Boost 库之间通常能够很好地协同工作,因此您可以轻松地将它们组合在一起,以满足特定需求。
跨平台性:Boost 在多种操作系统和编译器上都能正常工作,因此它具有很强的跨平台性。
社区支持:Boost 是一个由社区驱动的项目,拥有广泛的用户和开发者社区,因此您可以在社区中获得支持和解答问题。
C++标准化贡献:Boost 库中的一些功能已被采纳并成为 C++ 标准库的一部分,如智能指针 (std::shared_ptr
、std::unique_ptr
) 和正则表达式 (std::regex
)。
要使用 Boost 库,通常需要将其源代码包括头文件和库链接到您的项目中。您可以在 Boost 官方网站上找到详细的文档和教程,以帮助您入门和使用 Boost 库的各个组件。Boost 提供了广泛的文档和示例代码,以便您更好地理解和使用这些功能。
1 | find_package(Boost 1.86 REQUIRED COMPONENTS system filesystem PATHS "${BaseDIR}/packages/boost_1_86_0/lib/cmake/Boost-1.86.0/" ) |
Boost 是一个功能强大的 C++ 库集合,为开发者提供广泛的、可移植的功能扩展。它被设计为标准库(STL)的补充,是现代 C++ 编程的重要工具。Boost 提供了许多高质量的库,涵盖了文件系统操作、多线程处理、智能指针、正则表达式、图算法等多个领域。
std::shared_ptr
和正则表达式。以下是一些常用的 Boost 模块及其功能:
Boost.SmartPtr
提供智能指针(如 shared_ptr
, weak_ptr
),简化内存管理。
1 | #include <boost/shared_ptr.hpp> |
Boost.Regex
提供强大的正则表达式功能,类似于 std::regex
。
1 | #include <boost/regex.hpp> |
Boost.Thread
实现多线程编程,包括线程同步工具(如 mutex
和 condition_variable
)。
1 | #include <boost/thread.hpp> |
Boost.Filesystem
提供跨平台的文件和目录操作。
1 | #include <boost/filesystem.hpp> |
Boost.Asio
支持异步输入输出(I/O)操作,用于网络编程和异步任务管理。
1 | #include <boost/asio.hpp> |
Boost.Serialization
支持对象序列化和反序列化。
1 | #include <boost/archive/text_oarchive.hpp> |
Boost.Graph
提供图算法和数据结构,用于复杂的图计算。
下载与安装:
1 | ./bootstrap.sh |
项目中使用 Boost:
1 | g++ main.cpp -I /path/to/boost/include -L /path/to/boost/lib -lboost_system |
Boost 库是一个流行的 C++ 库集合,提供了各种各样的模块和功能,涵盖了多个领域,包括但不限于数据结构、算法、多线程、文件系统、网络编程、数学计算等。下面是一些主要的 Boost 模块:
Boost.Asio:提供异步 I/O 和网络编程功能,包括套接字、TCP、UDP、定时器、异步任务等,用于构建高性能网络应用程序。
Boost.Beast:基于 Boost.Asio,提供对 HTTP、WebSocket 和网络通信的支持,简化了处理 HTTP 和 WebSocket 协议的操作。
Boost.Filesystem:提供了对文件系统操作的抽象接口,包括文件路径操作、文件/目录的创建、删除、移动、复制等。
Boost.Thread 和 Boost.Atomic:提供了多线程和原子操作的支持,使得在 C++ 中更容易编写并发代码。
Boost.Container:提供了一系列 STL 容器的扩展和优化版本,如 flat_map、flat_set、static_vector 等,增强了标准库中的容器功能。
Boost.Graph:提供了图论相关的数据结构和算法,包括图的表示、遍历、最短路径等操作。
Boost.Math:提供了数学计算的库,包括数值计算、特殊函数、概率分布、统计函数等,用于处理数学问题。
Boost.Serialization:提供了用于对象序列化和反序列化的库,可以将对象转换为字节流以便存储或传输,并从字节流恢复为对象。
Boost.Regex:提供了正则表达式的功能,用于文本匹配和处理。
Boost.Date_Time:提供了日期和时间处理的库,包括日期时间表示、格式化、时区处理等。
Boost.PropertyTree:用于处理树状结构的数据,例如 XML、JSON 等格式的数据。
Boost.UUID:用于生成和操作 UUID(通用唯一标识符)的库。
Boost.Test:提供了单元测试框架,用于进行 C++ 程序的单元测试。
Boost.Locale:提供了本地化和国际化支持,包括字符集转换、日期时间格式化、货币格式化等功能。
Boost.Process:提供了对进程的管理和操作功能。
以上列举的模块只是 Boost 库中的一小部分,Boost 还包含许多其他模块和库,每个模块都专注于不同的领域,为 C++ 开发提供了广泛的工具和功能支持。每个模块都有其自己的文档和用法,开发者可以根据需要选择并使用适合的模块。
要将 boost::filesystem::path
转换为 std::string
,你可以使用 boost::filesystem::path
对象的 string()
成员函数。这个函数返回一个表示路径的 std::string
。以下是一个示例:
1 | #include <boost/filesystem.hpp> |
在这个示例中,filePath.string()
函数将 boost::filesystem::path
对象 filePath
转换为一个 std::string
,然后我们将其打印出来。
boost::ignore_unused()
不是一个函数,而是一个辅助函数宏,用于防止编译器产生“未使用变量”的警告。这个宏是在 Boost 库中定义的,位于 <boost/core/ignore_unused.hpp>
头文件中。
在 C++中,如果你声明了一个变量但在后续的代码中没有使用,编译器可能会发出警告。为了避免这样的警告,可以使用 boost::ignore_unused()
来告诉编译器你有意不使用这个变量。
下面是 boost::ignore_unused()
的简要说明和示例:
函数签名:
1 | template <class... Ts> |
这个宏接受任意数量的参数,并在编译时告诉编译器忽略这些参数的未使用警告。
使用场景:
boost::ignore_unused()
来避免编译器产生未使用变量的警告。示例:
1 | #include <boost/core/ignore_unused.hpp> |
在这个示例中,boost::ignore_unused(x)
告诉编译器忽略变量 x
的未使用警告。这在一些情况下很有用,例如在编写模板代码时,你可能有一些参数是在某些情况下使用的,但在其他情况下可能未使用。
总的来说,boost::ignore_unused()
是一个方便的宏,用于防止编译器因未使用变量而产生的警告。