- 博客(30)
- 收藏
- 关注
原创 一文读懂sizeof...运算符及其具体应用
专门用于在模板参数包(template parameter pack)中获取参数的个数。它与普通的 sizeof 运算符不同,后者用于获取类型或对象的内存字节数,而 sizeof... 用于计算参数包中包含的参数数量。if constexpr可以通过在编译期间确定表达式的条件真值,确定实际需要执行的代码块。这样就把一个目标功能,都集中在了一个函数体中,与我们通常书写递归函数的写法非常类似。基于上一个例子,我们必须得为终止条件专门写一个独立的终止函数。不是获取变参的总大小,而是获取变参的数量多少。
2026-05-19 08:52:08
115
原创 C++变参模板的简单入门
如各位开发者所熟悉的,在编写C++,或者阅读大量源码的时候,会遇到一个名为std :: bind的函数。该函数能够将对象绑定到函数或者可调用对象上。在一些情况下具有非常实用的效果。但是在早期 C++ 中有一个问题,那就是std :: bind能传入的参数非常有限,虽然在多数情况下能满足需求,但总有非常棘手的情况。这个问题直到 C++11 引入了变参模板的新特性才得以解决。本文主要讲解在 C++11~17 中,关于变参模板的一些核心使用。本文只涉及模板函数的使用,不会涉及模板类。
2026-05-18 16:05:16
123
原创 外出旅游路径规划探索
旅行商问题的解决在许多实际应用中都具有重要意义。尽管旅行商问题在描述上显得简单,但其计算复杂性使其成为一个具有挑战性的问题。对于 n 个城市,存在 n!(n 的阶乘)种可能的路径,穷举所有可能性在大规模问题上是不现实的。这个问题的复杂性归结为它的 NP-hard 性质,即在多项式时间内很难找到一个确定的最优解。为了解决这一问题,许多算法和策略被提出,其中一些是近似算法,能够在合理的时间内找到接近最优解的解决方案。
2026-05-18 08:55:52
144
原创 遍历算法:二叉树最大深度的解题思路
动画中绿色节点代表当前正在参与搜索的子树,蓝色节点代表已经计算出最大深度的子树,而橙色节点代表在最大深度路径上的节点。,至少需要将树中的每个叶子节点都访问一遍,前面学的二叉树的深度优先搜索算法就派上了用场。1. 二叉树的最大深度为左子树的最大深度和右子树的最大深度中的最大值再加一。2. 要计算当前二叉树的最大深度就必须提前知道左右子树的最大深度。3. 先访问左右子树,再访问根节点,所以应该使用后序遍历。但是具体该用先序遍历、中序遍历还是后序遍历来实现呢?计算二叉树的最大深度。下面给出了参考步骤;
2026-05-17 17:52:01
16
原创 二叉树的先序遍历的非递归实现
一般来说,二叉树的先序遍历(也称前序遍历)是一种深度优先遍历方式,其访问顺序遵循“根左右”原则,即:访问根节点;递归地先序遍历左子树;递归地先序遍历右子树。
2026-05-17 09:19:18
21
原创 原型设计工具Adobe XD2025全流程安装教程实录
网页设计:使用布局网格、响应式工具创建适配多端的界面;移动应用设计:内置 iOS/Android 模板,支持触摸手势、语音等交互;团队协作:通过共享链接收集反馈,支持多人同时编辑;用户测试:生成可点击原型,记录用户行为并优化体验。
2026-05-16 13:54:15
1189
原创 如何确认Python中客户端是否收到了服务端的消息
eventlet 是一个用来处理和网络相关的 python 库函数,而且可以通过协程来实现并发,在 eventlet 里,把 “协程” 叫做 greenthread(绿色线程)。
2026-05-16 09:27:21
36
原创 C++20的std::source_location
若它存在使用方式也非常简单,由于是和调用点有关,所以不用担心上面使用 __LINE__ 的问题。为了处理上述封装为函数出现的问题,C++20 推出了 std::source_location。
2026-05-15 19:39:52
35
原创 socket相关的部分常用函数学习
接受 UDP 套接字的数据。与 recv() 类似,但返回值是(data,address)。其中 data 是包含接收数据的字符串,address 是发送数据的套接字地址。将 string 中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。发送 TCP 数据。将 string 中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于 string 的字节大小。将数据发送到套接字,address 是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。
2026-05-15 12:30:14
11
原创 RAII妙用:控制台输出颜色的变化
如果是在调用点外部操作,则又是一种两面夹击的编写样式。但用了 RAII 便可以使得代码变得非常简洁。控制台的颜色我们是可以手动控制的,格式为 \033[属性1;属性3m(属性均可选)。比如在使用一个函数时需要进行一个特定的设置或者状态,而推出时又要回到调用点前的状态。为了让状态恢复,在析构函数中重新输入 \033[0m 即可。* 注意:这是对控制台的作用,输出到文件中便没有效果了。在软件开发过程中,有很多地方需要。
2026-05-14 11:39:20
34
原创 如何在C++中使用标准库的智能指针
此处代码较短不容易出错,但是当代码量越来越大,各种情况越来越复杂后就很容易遗漏最后的 mutex.unlock();此时就可以使用 RAII 的方式,在构造的时候对 mutex 进行 lock() 操作,在 unlock() 进行解锁操作。并且在使用资源前进行上锁的 lock() 操作,在使用完毕后用 unlock() 进行解锁。在多线程编程中,为了保护共享资源,我们通常会使用 互斥量 mutex 来进行保护。* 注意,在使用数组的时候需要使用数组的特化版本。这里假定在 2000ms 后两个线程都会结束。
2026-05-13 21:51:35
30
原创 技术分析:RAII在C++中的妙用
如大家所了解的,RAII全称为Resource Acquisition Is Initialization,直译过来就是 资源获取即初始化。这是一种在 C++ 中非常常见和核心的技术。它是由 C++ 之父 Bjarne Stroustrup 提出。最直接朴素的效果和作用就是对象在初始化时候执行构造器,生命周期结束时执行析构器。
2026-05-13 11:53:32
33
原创 状态机制表及种类分析
再根据上方的流程图,可以再抽象出两个状态分别为:符号处理状态 StateSign 和数值处理状态 StateDigit。一般来说,普通的流程化解法其实并不困难,但是对于思路不是很清晰的初学者朋友来说,一遍写出无错的代码并不简单。首先对于任意状态机我们都可以设置一个起始状态标志 StateStart 和终止状态标志 StateEnd。很大一部分原因在于在顺序遍历整个串时缺乏对每种状态的逻辑关系和转移关系的真正思考。并且一些字符会出现让状态保留的情况,如连续出现两个前导空格,则还是保留在起始状态。
2026-05-12 14:43:20
197
原创 对于C++中push_back的原理介绍与分析
首先我们都清楚 push_back() 的作用是复制或移动的方式向容器尾部添加给定的元素。函数接口如下面两个形式。这里有一段简单的代码,向一个 std::vector<std::string> 添加一个字符串。其中 arr.push_back("Hello World");的参数是一个字符串字面量。
2026-05-12 11:33:00
34
原创 二分查找算法:左闭右开区间
下图中灰色区域表示已经排除搜索的区间,白色区域表示当前正在搜索的区间,图中三个游标分别指向当前搜索区间的左端 st,右端 ed 和中间位置 mid。可以发现 st 游标始终指向搜索区间的左边界位置,ed 游标始终指向搜索区间。,但是两种不同实现最终定位到的目标元素位置是相同的。和左闭右开区间不同,全闭区间的 ed 游标。
2026-05-11 16:29:22
113
原创 软件设计原则之DIP依赖倒置原则
无脑的开发者容易直接重新写一个 Sqlite 类,并将 Application 中原先使用 Mysql 的地方全部替换。这显然是很低级的操作。随着程序的开发和团队的各种决策问题,此时有可能需要更换数据库,如从 Mysql 数据库换成 Sqlite 数据库。Mysql 数据库分别具有连接,断开关闭,执行 sql 语句等操作。因此基于单一职责原则可以单独封装起来。在一个应用程序 Application 中需要使用到数据库,比如我们此时需要使用到 Mysql 数据库。抽象不应该依赖细节;细节应该依赖于抽象。
2026-05-11 11:51:46
121
原创 PDF神器-Acrobat DC最新中文版下载与保姆级安装教程
创建PDF:从Word、Excel、PPT、网页、图像或扫描件转换为PDF;支持OCR(光学字符识别),将扫描件转为可搜索、可编辑文本。编辑内容:直接修改PDF中的文本、图像、字体、格式;重组页面(增删、排序、裁剪、旋转)。电子签名与安全:添加数字签名或手写签名;设置密码保护、限制打印/复制/编辑权限;添加水印或红字标注敏感信息。格式转换:将PDF导出为Word、Excel、PPT、RTF等格式,保留原布局。
2026-05-10 19:05:02
657
原创 软件设计原则之OCP开闭原则
在开发过程中我们需要对我们使用的对象进行多步的组合操作,比如这里要打印账户和密码信息。但是当你在一个大型团队中进行多人协同开发的时候,并不是你想直接在别人的类添加代码就能添加的。这就是所谓的要对修改进行关闭。一个比较合理的方式就是在模块的外部进行功能的扩充,这里编写一个全局的 to_string() 函数来满足我们的需求。常规的方式就是在外部直接进行调用,或者在类的内部添加新的 to_string() 方法。如果这是你一个人开发的内容,那直接在 UserInfo 中添加接口没人会管你。
2026-05-10 14:44:55
26
原创 线程取消stop token的实例分析
而都在关联了 jth 对象后,无论是对象析构前还是后,两者的行为是一致的。其中 if 的条件判断就是判断我们调用的线程函数的第一个参数是否是 std::stop_token。std::stop_token 提供一种检查与其所关联的 std::stop_source 对象作出停止请求的方法。其中 std::jthread 相较于 std::thread 有三个重要的新加接口。std::stop_source 提供一种请求发出请求的方式,可以用于请求结束 std::jthread。
2026-05-09 13:55:58
21
原创 关于C++中new的重载全局和类特定
想必大家都知道,在C++中能够对运算符,如+,-,*,/,%,<,>等等,进行重载。而和不但是关键字也是一种运算符,也可以进行重载。具体的在 C++ 中 new 重载形式非常多,下文主要常见的三种形式进行介绍。
2026-05-08 17:58:17
36
原创 编程狂想曲:复盘让代码更稳健
对于一个优秀的程序员,编程的方式永远是先思考,再动手。哪怕是写一个小函数,也先花几分钟想想:输入是什么?想得越深,代码越稳。反之,不经过充分的思考,写得越快,返工也越快。俗话说:“三思而后行。”在编程的世界里,这句话应该改成:“三思而后码。养成复盘的习惯,程序才会更稳健,程序员才更容易成长。久而久之考虑问题也会更加全面。所以重要的不是写出了多少行代码,而是写出来的代码背后,经过了多少扎实的思考。编程不仅是写之前要想,写之后也要想。
2026-03-16 18:02:53
23
原创 编程狂想曲:“写”的价值
此外,“写”本身也是对“想”最好的校验。当你写代码时卡住,这往往不是一个“不会写”的信号,而是一个强烈的需要重新“想”的提示,在此刻停下来,重新梳理逻辑,补全遗漏的细节再继续前行,效果会事半功倍。一旦跨过这个阶段,编程的重心就会立刻迁移到“在哪里画线”的思考上。实际上,小编并不是否定“写”的价值,对于初学者而言,可以说“写”比“想”更重要。因为初学者面对的首要困境不是“知道在哪画线”,而是“不知道怎么拿起粉笔”。这个“有思路却写不出”的阶段很容易让人产生一种错觉:“写”比“想”更难、也更重要。
2026-03-14 08:11:14
32
原创 编程狂想曲:让AI成为编程伙伴
最近几年,AI编程助手成为了我日常工作的重要伙伴。这让我更加深刻地体会到,程序员应当把时间花在梳理程序逻辑和定位问题上,而不是埋头敲代码和调试。只要需求足够清晰,AI 就能直接生成可用的脚本。虽然我不熟悉 bat 语法,但我能基本看懂代码逻辑、判断它是否符合我的预期,同时进行必要的修正。假如我是一个对 Windows 批处理(bat)语言一窍不通的小白,但我却用它写了不少自动化脚本。秘诀就在于我会清楚地向 AI 表述需求。AI 可以帮你写代码,但它不会读心术,不能替你思考。
2026-03-12 17:42:30
308
原创 编程狂想曲:修复Bug要三思而后行
最终解决方案不是优化代码,而是调整任务调度策略——为对账任务加上一个随机延迟(jitter 参数),把所有用户的对账任务打散,分布到非高峰时段。于是他又花了很长时间去修正代码——在收到时区变化的广播后,先把需要的数据初始化好,再去切换时间格式。我在 review 这些改动时,还没有具体看修改的细节,就先产生了疑惑:App 启动前,真的需要处理时区变化的广播吗。,是团队里遇到的一个程序崩溃问题:App 在启动前,如果收到了时区变化的广播,尝试切换时间格式会出现 crash。
2026-03-11 16:49:41
203
原创 经典算法题学习之矩阵(三)
但是,别忘了我们的题目中会有不止一个 0,这样以来,如果我们要使用第一种做法,就必须对于每个 1 计算一次它到所有的 0 的距离,再从中取一个最小值,时间复杂度会非常高,无法通过本地。处理的方法很简单:我们在进行广度优先搜索的时候会使用到队列,在只有一个 0 的时候,我们在搜索前会把这个 0 的位置加入队列,才能开始进行搜索;在广度优先搜索的每一步中,如果我们从矩阵中的位置 x 搜索到了位置 y,并且 y 还没有被搜索过,那么位置 y 离 0 的距离就等于位置 x 离 0 的距离加上 1。
2026-01-18 09:13:30
59
原创 经典算法题学习之矩阵(二)
对于矩阵中的每一个元素,如果它的值为 0,那么离它最近的 0 就是它自己。如果它的值为 1,那么我们就需要找出离它最近的 0,并且返回这个距离值。那么我们如何对于矩阵中的每一个 1,都快速地找到离它最近的 0 呢?0,我们应该怎么做?由于矩阵中只有一个 0,那么对于每一个 1,离它最近的 0 就是那个唯一的 0。如何求出这个距离呢?其中只有一个 0,剩余的 1 我们用短横线表示。我们不妨从一个简化版本的问题开始考虑起。假设这个矩阵中恰好只有。
2026-01-17 16:12:01
50
原创 详谈:二叉树的直径(二)
如图我们可以知道路径 [9, 4, 2, 5, 7, 8] 可以被看作以 2 为起点,从其左儿子向下遍历的路径 [2, 4, 9] 和从其右儿子向下遍历的路径 [2, 5, 7, 8] 拼接得到。首先我们知道一条路径的长度为该路径经过的节点数减一,所以求直径(即求路径长度的最大值)等效于求路径经过节点数的最大值减一。而任意一条路径均可以被看作由某个节点为起点,从其左儿子和右儿子向下遍历的路径拼接得到。
2026-01-14 08:52:36
43
原创 详谈:二叉树的直径(一)
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。两结点之间的路径长度是以它们之间边的数目表示。
2026-01-13 20:58:38
128
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅