自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

陈大大陈的博客

愿幸福降与此手。

  • 博客(98)
  • 收藏
  • 关注

原创 基于 C++ 的用户认证系统开发:从注册登录到Redis 缓存优化

基于轻量 HTTP 库httplib搭建接口,结合 MySQL 实现用户数据持久化,利用 Redis 构建高性能缓存层,搭配nlohmann/json处理数据交互。

2025-04-24 09:10:19 868 4

原创 用共享内存和 FIFO 实现高效 IPC:从代码实战到原理深度剖析

大家好,今天咱们聊聊程序员界的「内存快递站」—— 共享内存。这玩意儿能让两个程序在内存里直接「传小纸条」,比发微信还快(毕竟不用走网络)。咱们用两段魔性代码演示,顺便聊聊怎么避免让程序在内存里「打架」。

2025-04-21 21:31:12 807 3

原创 Trie 树核心代码拆解:如何用 200 行实现搜索引擎级联想功能?

想象你有一个超级字典,输入「app」就能秒变「apple」「application」「applet」…… 这不是魔法,是 Trie 树(前缀树)在搞事情!你的代码里,Trie 树就是核心「单词挖掘机」,专门挖所有以输入前缀开头的单词。

2025-04-18 15:41:08 626 2

原创 C++ 异常处理:从入门到精通的 20 个实战技巧

想象一下,你正在驾驶一辆满载乘客的大巴车,突然遇到前方道路塌陷。如果没有刹车系统,大巴会直接冲进坑里;如果有刹车系统但没有安全带,乘客会在急刹车时受伤。C++ 异常处理机制就像是程序世界的 "刹车 + 安全带" 组合,让你在遇到意外时能够安全停车并保护资源。在 C++ 中,异常处理是一把双刃剑:用得好可以写出健壮的代码,用得不好会导致程序崩溃或性能下降。本文将通过 20 个实战案例,带你从基础到高级全面掌握 C++ 异常处理的核心技术,包括:异常处理的底层原理自定义异常体系设计多线程环境下的异常

2025-04-13 11:49:17 1372

原创 【进来抱佛脚!蓝桥杯省一通关秘籍】从入门到开挂的核心技术全解析!

蓝桥杯因为台风延期了,正好方便大家再磨磨刀,我这个前省一就为大家准备了一些常用的模版,进来看看吧。

2025-04-12 15:34:36 925

原创 【红黑树养成记】从 0 到 1 实现你的专属 map 和 set,看这篇就够啦~ ✨

大家好呀~今天我们要认识一位超厉害的 “树界明星”——红黑树!它是一种自平衡的二叉搜索树,通过给每个节点涂上红色或黑色,严格遵守四条 “自律规则”,让自己始终保持 “优雅平衡”:根节点永远是小黑(黑色)小红(红色节点)的爸爸和叔叔必须是小黑(黑色节点)从任何节点到其后代空节点的路径上,黑色节点数量相等空节点视为小黑(黑色)正是这些规则,让红黑树在插入、删除时能快速调整,时间复杂度稳定在 O(logN),比普通二叉搜索树 “防秃” 能力强太多啦!💪 

2025-04-11 19:44:40 1195 3

原创 嘿!一起闯入 C++ 继承的魔法小镇

小镇里有一种神奇的魔法 —— 虚继承!就像一把闪耀着光芒的魔法钥匙,能解开这个迷局。当在 class B : virtual public A 和 class C : virtual public A 中加上 virtual 魔法咒语后,B 和 C 不再是各自复制祖先的魔法,而是共同守护着一份祖先的魔法力量。这样,D 就只有一份清晰明确的 _a 魔法,使用起来得心应手,二义性问题瞬间消失得无影无踪。

2025-04-10 17:13:32 833 2

原创 从零打造「轻量版 stdio」:文件操作背后的缓冲区奥秘

想象你每天往快递站寄小物件:如果每次寄一张明信片都单独叫一次快递,效率极低(就像频繁调用系统调用write);但如果攒够一堆再打包寄出(先存在缓冲区),就能大幅减少沟通成本。计算机的文件操作也是同理:通过缓冲区暂存数据,减少对磁盘的直接操作次数,这就是「缓冲 IO」的核心思想。

2025-04-08 16:08:44 570

原创 自制简易 Shell:像搭建积木小屋一样打造命令交互小天地

啥是 Shell 呢?打个比方,它就像是你和计算机底层系统之间的 “翻译官” 和 “大管家”。你给它下指令,它就能帮你调动计算机的各种资源去完成任务,就像你跟管家说 “我要整理文件”,管家就会去安排人手(计算机资源)帮你搞定。

2025-04-07 21:50:36 965

原创 进程池大揭秘:打造高效任务处理的 “奶茶工厂”

老板要给员工和自己弄个沟通渠道,代码里通过pipe系统调用创建管道,就像拉了根 “通话线”,专门用来传订单(任务指令)。接着用fork创建子进程,这就好比老板复制出一个个员工,每个员工都有自己的 “工作位”(进程 ID)。在员工这边(子进程),要是之前有别的 “通话线”(旧管道),就得先关掉,然后专心用新的 “通话线” 接收订单。而老板(父进程)则把和员工沟通的 “通话线” 一端(写端文件描述符)存好,方便之后派活。

2025-04-07 09:17:33 860 3

原创 让代码成为高效打工人:C++ 线程池设计与实现

想象你开了一家奶茶店: - 高峰期顾客(任务)络绎不绝,你得临时雇很多临时工(线程),但闲时他们就摸鱼聊天 - 频繁招聘解雇(创建销毁线程)成本高,还容易手忙脚乱。线程池就像个智能管家: - 固定数量的长期员工(线程),永远待命 - 任务来了按顺序处理,闲时自动休息(休眠) - 老板(主线程)只负责派单,不用管员工怎么工作。线程池耗时0.08s,内存12MB。直接创建耗时1.2s,内存89MB。

2025-04-06 21:39:52 752 1

原创 解决docker部署的容器第二天访问报错139的问题

最近部署了一个项目,一开始数据库在宿主机上,电脑重启之后docker会把宿主机数据库删除掉,我还没有备份,被整的苦不堪言。于是我就想着把数据库也部署上去,结果第二天进入数据库容器再看,数据还在,可是部署的服务访问不了了,并且报错139。

2025-04-03 17:25:39 503 3

原创 什么是尾递归及如何优化

尾递归会在栈上多次开辟空间,空间复杂度是O(N)。而循环的空间复杂度是O(1)。可以看到,在时间复杂度相同的情况下,循环的空间复杂度优于尾递归。所以我们得出结论,对于尾递归,我们尽量将其改写成循环的形式。

2025-03-08 15:31:57 232

原创 TCP连接秘籍:三次握手建立连接,四次挥手优雅告别

通过三次握手,客户端和服务器都确认了双方的发送和接收能力,连接得以成功建立,双方进入ESTABLISHED状态,可以开始数据传输。服务器收到客户端的ACK报文后,也确认了自己的发送能力和接收能力都正常,于是服务器状态也变为,连接正式建立。这样,通过三次握手,客户端和服务器都确认了双方的发送和接收能力,连接得以成功建立。四次挥手的过程确保了TCP连接的双方能够优雅地释放连接并释放资源。通过四次挥手,连接双方都能确认对方已经收到了关闭请求,并且所有数据传输都已经完成。

2024-11-15 20:53:08 782 4

原创 Git全攻略:从基础到高级协作,一站式掌握版本控制精髓

欢迎踏入Git的奇妙魔法世界,一场穿梭于代码海洋中的奇幻旅程即将启程!🧚‍♂️想象一下,你手中握着的不仅仅是一个版本控制系统的钥匙,而是通往无限创意与完美协作的神奇门扉!🌟在这里,每一次commit都是一颗璀璨的星辰,在浩瀚的代码宇宙中留下你的智慧轨迹。🌌而branch,则是你的秘密花园,让你在不受干扰的天地里自由探索、大胆尝试,即使偶尔迷路,merge总能温柔地带你回归主路,拥抱变化,共同成长。🌱别担心,即使你是编程界的小萌新,Git也会用它那温暖而强大的怀抱,一步步引导你学会时间旅行,轻

2024-11-04 07:00:00 815 10

原创 【C++智能指针深度解析】std::shared_ptr、std::unique_ptr与std::weak_ptr的构造、原理及应用实战

智能指针是C++11引入的新特性,因为C++使用内存的时候很容易出现内存泄漏、野指针、悬空指针的问题,所以C++11引入了智能指针来管理内存。这篇文章会详细介绍了三种智能指针:、和的原理、使用方法和适用场景。共享式指针,同一时刻可以有多个指针指向一个对象。shared_ptr对象一旦被销毁,或者其值通过赋值操作或显式调用shared_ptr::reset而发生变化,就会立即释放它们共同拥有的对象的所有权。 shared_ptr指针的对象有获取指针所有权以及共享该指针所有权的能力,一旦它们获取了所有权,当最后

2024-10-24 21:59:36 1310 5

原创 揭秘Git合并机制:为何先commit后pull再push,避免代码覆盖的真相

首先,在多人协作的环境中,远程仓库是团队成员共享代码的地方。在提交自己的改动之前,先拉取远程仓库的改动,可以及时发现并解决潜在的代码冲突。,再次 pull 一次是为了防止在你们协商的时候另一个人给又提交了新的一版东西,如果是这样,那上面的流程就再重复一遍,通常没有冲突的时候就直接给你合并了,而并不会把你的代码给覆盖掉。(或Rebase,取决于您的配置):将远程仓库的改动与你的本地改动合并。这位兄台对于pull有个误区,他认为pull会直接将远程仓库的代码覆盖到本地,实则不然。,我们来深入理解一下pull。

2024-10-22 16:30:00 2044 4

原创 深入理解inet_addr函数:点分十进制IPv4地址到4字节网络字节序的转换

点分十进制(Dotted Decimal Notation,简称DDN)是一种用于表示IPv4地址的标准格式。IPv4地址是一个32位的数值,为了便于人类阅读和理解,它被分为4个字节(每个字节8位),并以点()分隔。每个字节的数值被转换为十进制数,并依次排列,用点号连接,从而形成一个点分十进制的IPv4地址字符串。例如,IPv4地址就是一个点分十进制格式的地址。1921681和1,每个部分都是一个十进制数,它们分别对应IPv4地址中的四个字节。

2024-10-22 15:13:51 2180

原创 C++虚函数表深度剖析

只要一个类中有虚函数,那这个类中就一定会有一张虚函数表,虚函数表中的每一项都是虚函数的地址。这个类的每一个对象都会包含一个虚指针(虚指针存在于对象实例地址的最前面,保证虚函数表有最高的性能),这个虚指针指向虚函数表。

2024-10-20 21:41:15 563

原创 动态内存管理及RAII的简单应用

dll文件是Dynamic Link Library()文件的缩写,它是一种共享库文件,包含了程序所需的代码和数据。与静态链接库不同,动态链接库,使得程序的内存占用更小,同时也方便了程序的更新和维护。程序启动时,系统会将exe主程序依赖的所有dill库文件加载到进程的代码段的内存区中,这些文件里存放的是可执行的二进制机器码,也就是汇编代码。

2024-10-19 11:29:37 825

原创 线程互斥补全和加锁原理

可是此时寄存器内已经是0,它交换之后会做判断,如果是大于0,就执行,等于0,就挂起等待。操作时,以一条汇编指令的形式交换寄存器和内存单元中的数据,将寄存器的1和a来交换。为了方便理解,我们把锁简单理解成包含整形1的一个结构体,在内存单元中。要解决饥饿问题,就要使多线程执行有一定顺序性,也就是线程同步。多线程运行时,一份资源,有进程长期无法拥有,造成饥饿问题。可以定义上面这样的类,自动析构就等于解锁,非常方便。如果这时线程时间片到了,第二个线程过来,也要交换。互斥锁可以是全局的,也可以像上面一样是局部的。

2024-04-19 15:31:55 393

原创 线程互斥及基于线程锁的抢票程序

根据互斥的定义,任何一个时刻只允许一个线程申请锁成功,申请失败的进程在mutex阻塞,本质就是等待。任何时刻,互斥保证只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用。首先把a从内存拷贝到CPU的寄存器,字CPU中完成++操作,再返回内存,不是原子的。可能大家会认为,当线程进入锁,执行锁内代码,这是如果发生切换,还是会产生同样的错误。其实这次不一样了,因为就算时间片到了,发生线程切换,被切换到的线程也没办法访问锁。申请锁本身是原子的,有宝马。就相当于上的线程的密码锁,专属的。

2024-04-18 22:24:33 998

原创 C++的线程

这样,我们学习别的语言,只需要学习接口,因为我们知道底层是一样的。用纯c++的接口创建线程时,在Linux中还是要包含线程库。这说明c++的那些库本质就是pthread原生线程库的封装。在编译链接库时,就会给每一个变量在线程局部存储中开辟空间。__thread可以给每个执行流一个变量。如果不添加-lpthread就会报错。说到底,这样的设计就是为了跨平台性。接下来了解一下线程的局部存储。下面是多线程的一个简单模版。

2024-04-18 13:37:05 438

原创 线程控制及线程底层原理

默认地址空间中的栈由主线程使用,这样,可以保证每一个新线程都可以保存要执行的方法,要传递的参数以及动态运行时的临时变量。同样的,pthread库也是库,在库中实现pthread_create的时候,内部包的就是clone函数。创建线程的时候,在正文代码区,直接跳转到共享区的库里,执行创建线程的函数,然后返回。7、用户栈:线程执行的用户方法栈,用来保存线程当前执行的用户方法的信息。而线程库是共享的,所以,内部要管理整个系统,多个用户启动的所有的线程。

2024-04-17 20:51:26 741

原创 多线程传参以及线程的优缺点

如果计算密集型 线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的 同步和调度开销,而可用的资源不变。linux没有真线程,只有轻量化进程,所以Linux OS只会提供轻量化进程的系统调用,不会直接提供线程创建的接口。编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了。与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多。而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。然后在软件层中,将线程对应成LWP。

2024-04-16 20:16:15 1102

原创 什么是线程?线程和进程谁更弔?

线程较进程更轻量化,调度上来说,pcb切换另一个pcb,地址空间,页表等是不用切换的,只需更换进程运行中寄存器产生的临时数据。线程的本质就是CPU调度的基本代码,Linux内核复用了进程代码,用进程pcb模拟充当线程。操作系统调度的时候,看的也是lwp,判断是主线程还是新线程,看的是lwp是否等于pid。换句话说,线程切换时,不需要切换CPU内部的所有寄存器的数据,而只需更换少部分。cache会对用户操作做出预判,加以缓存,大概率猜对,猜不对也没关系,重新缓存。

2024-04-16 00:58:34 648

原创 从零带你底层实现unordered_map的代码补全(2)

先把代码发出来,大家先看,有什么不懂得都可以私信问我。这块的迭代器是比较复杂,需要仔细看看。有问题题请私信 😘 😘 😘。

2023-12-04 12:41:19 840 4

原创 从零带你底层实现unordered_map的代码补全

改了一下开散列,加入了哈希桶,上期忘记加上了,现在补上,不好意思。

2023-11-28 14:58:43 530 2

原创 从零带你底层实现unordered_map (2)

💯 博客内容:从零带你实现unordered_map😀 作  者:陈大大陈🚀 个人简介:一个正在努力学技术的准C++后端工程师,专注基础和实战分享 ,欢迎私信!💖 欢迎大家:这里是CSDN,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘哈希/散列:映射,关键字和另一个值建立一个关联关系。哈希表/散列表:映射,关键字和储存位置建立一个关联关系。哈希/散列是一种算法思想,而哈希表/散列表是基于这种算法思想而实现的一种数据结构,这点很容易混淆。上一篇博客介绍了两个解决哈希冲突的方法,

2023-11-28 14:20:30 1365 22

原创 从零带你底层实现unordered_map (1)

它是一个单向的迭代器。为什么专门提到这个呢?因为这是我踩过坑的地方!!单向迭代器压根就不能使用sort函数来排序!std::unordered_map的迭代器类型是ForwardIterator,而不是sort函数要求的RandomAccessIterator,这里不符合。我们要排序的话,还是将unordered_map里存的值,转存到vector里面。然后我们再自定义一个排序方法,对vector进行排序。

2023-11-20 23:08:47 1175 19

原创 并查集模版以及两道例题

上面的时间复杂度最好能有O(1)。实现方式是记忆化搜索,用数组存储好所需结果,需要时就不用再次递归了。这种并查集查找的效率太低,最坏情况的时间复杂度能达到O(N)。我们就针对它优化。上面的时间复杂度最好能有O(1)。实现方式是记忆化搜索,用数组存储好所需结果,需要时就不用再次递归了。来看两个例题巩固一下。How Many Tables(并查集)Problem - 1213 (hdu.edu.cn)题目:Today is

2023-11-06 19:45:15 448 27

原创 多态 多继承的虚表深度剖析 (3)

这么打印,需要注意的是,d是一个Derive类,加一的话会加上一个Derive的大小。我没看到,编译器仍旧是故技重施,欺骗我们的眼睛,我们检测监测不到func3。但是这样的话,就会衍生出一个问题,它自己的虚函数也就是func3放在哪里呢?此时有看起来有3个虚表,其实还是2个。答案是,因为继承了Base1和Base2两个类,所以有两个虚表。上面这种多继承的情况,Derive有几个虚表呢?我们得到结论,func3放到了第一个虚表里面。答案是两张,这种情况就跟普通的多继承没两样。还可以这样写,最聪明的一种写法。

2023-11-05 22:08:45 1412 23

原创 多态 虚函数表深度剖析 纯干货讲解(2)

打开内存监视窗口,我们高度怀疑后面两个地址是被隐藏的两个虚函数的地址。虚函数和普通函数一样,存在代码段,同时将虚函数地址存了一份到虚函数表。第一次编译器出了bug,没有在虚表后标识上0,第二次就好了。终于到了放终结技的时候了,我们可以在打印的时候同时调用函数。上面我们埋下了伏笔,在命令行窗口会打印出来调用函数的信息。经过测试,虚表是储存在常量区的代码段的,跟常量很接近。虚表储存在类的前四个字节,我们就取这四个字节打印出来。并不是这样,监视窗口看到的内容是经过编译器处理的。看不明白的老铁可以看看上面的图。

2023-11-05 18:01:27 260 12

原创 C++ 多态 纯干货讲解 复制可调试(1)

从上面可以看出,C++对函数重写的要求比较严格,但是有些情况下由于疏忽,可能会导致函数名字母次序写反而无法构成重载,而这种错误在编译期间是不会报出的,只有在程序运行时没有得到预期结果才来debug会得不偿失,因此:C++11提供了override和final两个关键字,可以帮助用户检测是否重写。调用指针或者引用指向的对象,指向父类就调用父类,指向子类就调用子类。查找虚函数表中存储的地址,是父类就调用父类,是子类就切割成父类对象。答案是B,容易选成D,需要注意的是,虚函数继承声明,重写实现。

2023-11-04 22:50:11 305 16

原创 动态规划太难了?是你没有找对方法,四题带你搞懂动态规划!

动态规划太难了?是你没有找对方法,四题带你搞懂动态规划!

2023-10-26 23:47:04 461 16

原创 关于刷题时使用数组的小注意事项

在Windows下,栈的大小为2M,也就是1024*1024*2 = 2097152个字节。所有我们在程序中声明局部变量时(在栈区),最好不好超过int[200000]的内存变量。总之,当程序需要声明一个超过十万级的变量时,最好放在main函数外面,作为全局变量去使用。不然的话,可能像我上面那样发生栈溢出问题,还以为是代码的思路有问题。对于c语言,一个静态数组能有多大,取决于剩余内存的空间,也就是它所在区的大小;全局数组是存储在内存中的静态区,而局部变量是存储在栈区。

2023-10-20 12:00:53 414 18

原创 (面试)谈谈我对C++面向对象特性的理解

总的来说,面向对象是一种方法,这种方法是用来组织设计和实现的。组织设计就是找到解决问题的思路。实现就是把代码写出来。面向对象关键的核心在于,对象是组织和实现主要关注的东西,而不是过程。

2023-10-07 20:10:03 1058 21

原创 C++的范围for语句详解 附易错实例

在范围for语句中定义的变量,容器或者数组内的每个元素都必须能转换成该变量的类型。实例2:将字符串中所有的大写字母转化成小写字母,将所有的小写字母转化成大写字母。但是有一点要特别注意,刚才举的例子中的变量i实质是数组a中每个元素的。如果仅是修改变量i的值,数组a中的元素的值是不会变化的。范围for语句是C++引入的一个语法糖,例如,下面的代码让数组中每一个元素加三。这么一看还是范围for语句比较简洁。如果要通过变量i修改数组中变量的值,所有的元素都处理完毕后循环终止。让编译器帮助制定合适的类型。

2023-07-09 17:23:20 886 11

原创 C++的auto类型说明符详解 附易错实例

C++里没有越界检测机制,即使正整数的值已经超过了字符串的长度,循环体依旧可以成功运行。所以程序会莫名其妙的输出乱码。而且,即使i从正整数值递减到0,依然会因为刚才解释的原因再次回到那个非常大的正整数值。所以程序是一个死循环。要解决死循环也非常简单。

2023-07-08 21:49:14 1352 45

原创 C++ string中内置的字符串操作和标准库中常用字符处理函数

💯 博客内容:C++读取一行内个数不定的整数的方式😀 作  者:陈大大陈🚀 个人简介:一个正在努力学技术的准前端,专注基础和实战分享 ,欢迎私信!💖 欢迎大家:这里是CSDN,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘 😘 😘string中定义了求字符串长度,比较,拷贝等操作,并把他们封装成了一个个函数。

2023-07-07 20:37:46 616 3

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除