- 博客(235)
- 收藏
- 关注
原创 C/C++|如何使用GDB调试不带调试信息的可执行程序
该版本结合两者优点:包含了符号信息和调试信息,有被破解的风险;开启了优化,调试时可能和源码没法对应。如何使用 gdb 调试不带调试信息的可执行程序在 模式下,我们可以讲可执行文件和调试信息进行分离,其中的关键就是 调试链接。在线上环境,我们不公布调试信息(文件),如果线上有问题,我们可以加入 文件,并且只要可执行文件包含有调试链接(这里需要通过命令来实现)也就是说步骤如下:综上所述,我们就可以使用GDB调试不带调试信息的可执行程序。
2024-08-25 17:14:30 431
原创 C/C++|经典代码题(动态资源的双重释放与「按值传递、按引用传递、智能指针的使用」)
以下代码中你能看出其存在什么问题?如何修复,能给出几种方法?分别在什么场景下用哪种方法。代码简单介绍如下:给出两个类,一个是 buffer 管理器,底层是 buffer, buffer 管理器持有一个 buffer 指针,有一个 getBuffer 函数。主逻辑也很简单,就是构造 BufferManager,调用 getBuffer我们简单分析一下代码:我们在 getBuffer 中,是按值传递对象,这会导致对象被拷贝。
2024-08-20 20:40:27 419
原创 C/C++|C++标准库 string 流之std::ostringstream 和 std::istringstream 流
我们在 sstream 头文件中定义了三个类型来支持内存IO(ostringstream\istringstream\stringstream),这些类型可以向 string 写入数据,这里我们主要讲:和( C++ Primer 中文版第五版)以上的两个类型都继承自我们经常使用的 iostream 头文件中定义的类型。并且,他们还增加了一下成员来管理与流相关的 string。也就是说,他们使得我们能够像控制IO流一样控制 string。
2024-08-20 17:46:52 444
原创 C/C++|关于 std::priority_queue (优先级队列)的第三个模版参数
Lambda表达式当然了,我们也可以使用 std::function 直接声明 cmp 的类型:
2024-08-13 15:24:37 208
原创 LeetCode Medium|【200. 岛屿数量】
在代码随想录中写了深搜和广搜两个思路,并且它使用的是 ACM 模式。在这里,我们从 leetcode 的核心代码的角度来讲解核心思路。在基础的思路分析中,搜索网格的代码很简单,两个 for 循环,但是我们如何把相邻陆地都打上 “已访问” 标记呢?那就离不开我们的搜索算法来:DFS、BFS。
2024-08-12 12:01:02 335
原创 LeetCode Medium|【33. 搜索旋转排序数组】
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2]。核心的逻辑就是我们一定要在有序部分进行二分查找,当我们计算出 mid 之后,区间被分为左右两个部分,那么肯定至少有一个部分是有序的,甚至可能两个部分都是有序的(在进行到第二次切分之后,一定是左右两个区间都有序)。旋转排序数组:部分有序!
2024-08-12 11:24:19 184
原创 数据结构与算法|算法总结|动态规划篇之子序列、子数组问题
首先我们要明确以下两个问题:是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。是数组中的一个连续部分好了现在开始做总结!然后建议搭配食用。
2024-08-09 18:09:47 751
原创 数据结构和算法|递归算法那些事(递归算法的时间复杂度、尾递归优化、斐波那契数列)
每次n-1,递归了n次时间复杂度是O(n),每次进行了一个乘法操作,乘法操作的时间复杂度一个常数项O(1),所以这份代码的时间复杂度是 n × 1 = O(n)。每次递归了做都是一次乘法操作,这也是一个常数项的操作,那么这个递归算法的时间复杂度才是真正的O(logn)。尾递归优化既可以是语言级别的,也可以是编译器级别的,我们的 C++ 就是编译器级别的尾递归优化。当前这棵二叉树就是求x的n次方,n为16的情况,n为16的时候,进行了多少次乘法运算呢?所以,如果是求 x 的 n 次方,那么时间复杂度就是。
2024-08-08 16:53:05 820
原创 LeetCode Medium|【300. 最长递增子序列】
局部最优:如果我们希望上升子序列尽可能的长,则我们需要让序列上升得尽可能慢;全局最优:最终遍历完整个数组,那么此时的序列长度为最长递增子序列。如果你能了解二分查找找到插入位置的话,此题非常简单。本题有一个简单的解法是动态规划,时间复杂度。对于序列[0, 8, 4, 12, 2],第四步插入 12,d=[0,4,12];第五步插入 2,d=[0,2,12]。第二步插入 8,d=[0,8];第三步插入 4,d=[0,4];第一步插入 0,d=[0];
2024-08-07 15:28:00 255
原创 LeetCode Hard|【25. K 个一组翻转链表】
首先,做整表翻转的时候,我们的逻辑非常简单。这里简单直观多了,最大的区别是什么呢?
2024-08-06 17:50:14 371 1
原创 LeetCode Hard|【460. LFU 缓存】
private://从键到节点的映射//从频率到节点链表的映射//从节点到其在列表中位置的映射这里我们需要一个私有成员函数,也就是更新频率的函数,其实逻辑还是比较好理解的。//获取该频率对应的节点链表// 从该链表中删除该节点,因为该节点的频率注定被改变了// 如果当前频率的节点链表为空,删除该频率并更新最小频率//当前删除的频率链表为最小频率时,更新最小频率//增加节点的频率,并将其插入到新的频率-节点链表的最前面//记录每个节点在各自链表中的位置。
2024-08-04 16:02:21 440
原创 LeetCode Medium|【146. LRU 缓存】
题意:本题的题意就是希望我们设计一个满足 LRU 缓存的数据结构,LRU即最近最少使用。需要我们实现 get 和 put 方法,即从缓存中获取值和设置缓存中值的方法。还有一个约束条件就是缓存应当有容量限制,如果实现 put 方法的时候,没有空闲的空间的话,需要淘汰一个最久没有使用的 key同时要求 get 和 put 的时间复杂度是O(1)
2024-08-03 17:43:30 779
原创 LeetCode Medium|【3. 无重复字符的最长子串】
状态:在本题中,我们可以很明显得看出出现了关键字:子串、最长,所以我们肯定是选用滑动窗口来解决这个题目。滑动窗口首先要解决的就是我们选择什么样的容器来存储数据呢?本体中是计算重复字符,我们可以使用 set、map、数组均可以解决,这里分别给出三种方法。
2024-08-03 12:04:38 395
原创 LeetCode Easy|【21. 合并两个有序链表】
当然了还有一种更加简单的思路,其实思路上主体都是一致的,不过代码上会简单很多,但是他会有一个额外的空间来申请一个新的链表。随后的思路就是以第一条链表为基准完成插入,并且对于遍历到的每个节点都应该保存其状态。状态:拿到本题的第一反应就是使用双指针,分别指向两个链表的开头位置。写了一下代码后发现,我们应该以第一个节点较小的链表作为基准链表。随后就是开始我们的遍历操作了。
2024-08-02 17:38:05 309
原创 C++|设计模式(八)|⭐️工厂模式?错!是工厂模式群!
首先我们按照与 Employee 类相同的方式来创建所有不同项目对应的基类(父类)Project,在这个类中我们还定义了与项目相关的接口 assignTo ,这个接口可以将某个项目指派给对应账户ID的员工,还是相同的方式我们定义 ITProject 与 UIProject 这两个不同项目的子类,并提供 assignTo 接口的不同实现。
2024-08-02 16:30:45 1001
原创 LeetCode Easy|【35. 搜索插入位置】
也就是说,如果最终在数组中没找到 target 所处的位置的话,那么就应该使得 left 在不断得靠近 right ,最后也就是三位一体,也就是说至少可以保证, left 会最终指向应该插入 target 的位置。哈哈哈看着都想笑,虽然过了但是丑陋至极。其实还是没有搞清楚二分法的精髓。个人认为,这一题不会就是压根就没有明白二分查找,本人就是。状态:第一次做的时候瞎调了半天,后来沉下心来之后写了这样一段代码…
2024-08-01 17:36:45 308 1
原创 LeetCode Easy|【415. 字符串相加】
题目本身难度不大,但是后续的一些补充内容还是值得搞清楚的这样就可以完成字符串到整数的隐式转换。
2024-08-01 17:11:02 360
原创 C++|设计模式(七)|⭐️观察者模式与发布/订阅模式,你分得清楚吗
本文内容来源于B站:【「观察者模式」与「发布/订阅模式」,你分得清楚吗?】随后我们就可以调用 Stock 对象上的 setPrice 方法来更新股票价格,并且广告牌与显示器上的数字也会被相应更新。但是这样的实现方式有许多的问题:也就是我们的 Monitor 类和 Billboard 类都是观察者,这里我们可以提供一个统一的父类 Observer ,并且在里面写入 update 接口,这个接口将所有观察者在观测时发生的不同动作进行了统一的包装。Observer 的构造和析构会在后面进行补全:然后我们
2024-08-01 15:46:21 1256
原创 LeetCode Hard|124.二叉树中的最大路径和
题目解读:二叉树路径的定义即从1.任意节点出发,到达任意节点;2.该路径至少包含一个节点,且不一定经过跟节点;3.求所有可能路径和的最大值。也就是说路径途径一个节点只能选择来去两个方向考虑一个二叉树单元设计一个函数,它应该,所以该函数应该把 a 传入,然后递归调用 b 和 c ,计算 b + a 和 c + a,选择较大的值作为返回值,然后拿到全局最大和。(这里我们很容易确定参数和返回值,并且能够一探递归函数的单层递归逻辑)
2024-07-02 10:10:23 893
原创 C/C++|Pimpl Idiom(Pointer to IMPLementation) 指针实现模式浅析
Pimpl Idiom(Pointer to IMPLementation),也称为 “Opaque Pointer”(不透明指针)或 “Cheshire Cat”(柴郡猫)模式或者"指针实现模式"和"实现隐藏模式"。这种模式通过将类的实现细节放在一个单独的私有结构体中,并通过指针来访问,从而在不改变类接口的情况下,允许类的实现独立于类的定义进行修改和编译。Pimpl Idiom 的核心思想是将类的实现细节放在一个私有的实现类中,并使用指向该实现类的指针在公共接口类中进行引用。这种方式可以将类的实现细节完全
2024-06-10 16:41:10 630
原创 C/C++|关于 namespace 在C++中的代码组织
命名空间(namespace)在C++中用于组织代码,避免命名冲突,并提供更好的代码结构和可读性。下面详细解释命名空间在C++多文件编写中的各种作用和表达。命名空间是一个声明区域,用于组织代码,防止不同部分的代码中使用相同名称的符号(如函数、类、变量等)产生冲突。在上面的示例中,MyNamespace 包含了一个变量 myVariable 和一个函数 myFunction。文件结构示例假设我们有以下文件结构:在头文件中声明命名空间和其包含的函数:math_utils.cpp在源文件中定义命名空间和其
2024-06-10 14:24:16 543
原创 C/C++|std::function 浅度解析
std::function 是 C++ 标准库中的一个通用多态函数包装器。它可以存储、复制和调用任意可调用目标(函数、lambda 表达式、绑定表达式或其他函数对象)。std::function 占有固定尺寸的内存,这是因为它的实现方式决定了这一点。让我们深入探讨这一点。
2024-06-10 09:52:58 1149
原创 C/C++|类型推导中的模式匹配
/一次调用则形如:f(expr);在编译期,编译器会通过expr推导两个型别,一个是T的型别,一个是ParamType//ParamType 是 const T&//调用语句如下:int x = 0;f(x) //以一个 int 调用 f我们可以依靠直觉就能得出正确答案:T的型别是intParamType的型别是const int&「去掉参数类型中的const和引用符号」为什么能去掉他俩呢?
2024-06-09 15:12:32 455 1
原创 项目工具|git相关
我们现在如果想直接提交到版本库,在commit的时候,我们应该把所有的代码改动都应该说清楚,鉴于我们所改动的代码较多,一个commit感觉有点难说明白,因为我们在file1中开发了这老些功能,然后有的还没开发完,随后我们在file2中又开发完了a中没有完成的部分,你应该怎么描述这个commit呢?A分支和B分支同时修改了一个地方,他们两个代码都有用,但是我要重新调整一下组织形式,所以说我们就把代码改一改再提交。现在又了暂存区,我们可以选择暂存部分、单独的文件,甚至我们可以只暂存某些行甚至一行!
2024-06-07 13:26:04 1237
原创 C/C++|基于回调函数实现异步操作
今天我们讨论的是回调函数,我们如何通过回调函数来实现异步操作呢?我们就分别来实现一下他们吧,代码比较长,请耐心阅读。
2024-06-02 20:34:07 1109
原创 C/C++|关于C++的异常处理机制
来自C++入门选手的理解,希望有大佬看到可以指导补充首先我们需要先讨论一下assert宏,它仅用来捕捉不应该发生的逻辑错误,而且他也不能对错误进行处理,而是直接终止程序执行。随后我们来介绍C++的异常处理机制。它允许程序中独立开发的部分能够在运行时就出现的问题进行处理。整个行文的逻辑我想先说明 try … catch…块,也就是我们如何抛出异常和捕获异常,然后我们再细致讨论这两个概念。
2024-06-02 15:09:17 1078
原创 Linux|Linux系统的exec函数族浅浅解析
exec 函数族是 Linux 和其他类 Unix 操作系统中的一组系统调用,。这些函数包括 execl, execle, execlp, execv, execve, execvp 和 execvpe 等。。
2024-06-02 14:00:23 910
原创 操作系统|进程和线程的上下文以及他们的上下文切换具体流程?
进程和线程已经是老生常谈的问题了,现在那么他们是如何进行切换的呢?他们之间的切换有什么区别呢?如果你不懂的话,就让我们一起来探讨一下吧!
2024-06-02 13:30:19 1033
原创 操作系统|代表进程运行状态的各寄存器
本文主要资料来源于网络,这里只做一个简单的了解用,如果用错误还请读者指出指出。在CPU架构中,尤其是x86架构,代表进程运行状态的通用寄存器包括了几个关键的寄存器,这些寄存器存储了与进程执行直接相关的各种信息。
2024-06-02 11:36:33 451
原创 【C++集群聊天服务器(二)】|json简单入门
Json是一种轻量级的数据交换格式(也叫数据序列化方式)。也就是说,我们在数据的传输上其实已经被序列化了,等发到服务器或者是发到客户端的时候,我们需要把它反序列化成json。json长什么样子可以直接去百度即可。
2024-06-01 14:56:32 603
原创 【C++集群聊天服务器(一)】|Linux平台资源受限下boost库和muduo网络库源码编译安装
本人使用的服务器是2G2核 ubuntu22.04。
2024-06-01 13:59:10 671 1
原创 问题排查|记录一次基于mymuduo库开发的服务器错误排查(段错误--Segmentation fault (core dumped))
好巧不巧,我们竟然在生成epoll实例的地方返回了一个空!之前在写这个代码的时候还没有完成。出现多错误这通常意味着程序试图访问其内存空间中未分配(或不允许)的部分。在刚完成mymuduo库之后,写了一个简单的测试服务器,文件的书写,为了防止部分编译报错所以先写成空了。就发现我们重要的poller对象竟然是空!所以我马上去看了一下构造函数代码是否正常。但是比较悲剧的是,我直接。
2024-05-31 18:06:20 255
原创 C/C++|智能指针的shared_from_this和enable_shared_from_this
参考博客(或者叫摘抄的博客,本博客只做为个人学习使用):施磊老师牛逼。
2024-05-31 13:37:50 1292
原创 C/C++|我们为什么应该使用 `std::make_shared` 创建 `std::shared_ptr`
std::make_shared 是 C++11 引入的一个工厂函数,用于创建 std::shared_ptr。与直接使用 new 并将其传递给 std::shared_ptr 构造函数相比,std::make_shared 提供了一种更高效、更安全的方法来分配和管理动态内存。前置知识1:这一步创建了一个对象,分配了控制块的内存。控制块包含了引用计数等等信息。前置知识2:当你使用 std::make_shared 时,这两个步骤被合并为一个原子操作,。好了,从前置知识里我们应该就能大概猜到。
2024-05-31 12:01:30 1717
原创 C/C++|回调函数的正确打开方式
/ 设置自定义回调函数// 触发事件,调用回调函数// 输出:Event triggered with code: 42return 0;
2024-05-31 10:40:59 428
原创 C++语法|关于C++11线程类的线程回收技术:thread线程函数传参问题、std::ref、std::future、std::promise、std::packaged_task
在C++11中,虽然库中的std::thread没有直接类似于pthread_join()的功能来获取子线程的返回数据,但可以通过几种方式实现相似的功能,主要是使用std::future和std::promise,或者std::async来从子线程获取数据。
2024-05-29 21:25:31 1309
李宏毅老师语音识别课程
2023-09-12
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人