- 博客(87)
- 收藏
- 关注
原创 解决docker部署的容器第二天访问报错139的问题
最近部署了一个项目,一开始数据库在宿主机上,电脑重启之后docker会把宿主机数据库删除掉,我还没有备份,被整的苦不堪言。于是我就想着把数据库也部署上去,结果第二天进入数据库容器再看,数据还在,可是部署的服务访问不了了,并且报错139。
2025-04-03 17:25:39
190
1
原创 什么是尾递归及如何优化
尾递归会在栈上多次开辟空间,空间复杂度是O(N)。而循环的空间复杂度是O(1)。可以看到,在时间复杂度相同的情况下,循环的空间复杂度优于尾递归。所以我们得出结论,对于尾递归,我们尽量将其改写成循环的形式。
2025-03-08 15:31:57
188
原创 TCP连接秘籍:三次握手建立连接,四次挥手优雅告别
通过三次握手,客户端和服务器都确认了双方的发送和接收能力,连接得以成功建立,双方进入ESTABLISHED状态,可以开始数据传输。服务器收到客户端的ACK报文后,也确认了自己的发送能力和接收能力都正常,于是服务器状态也变为,连接正式建立。这样,通过三次握手,客户端和服务器都确认了双方的发送和接收能力,连接得以成功建立。四次挥手的过程确保了TCP连接的双方能够优雅地释放连接并释放资源。通过四次挥手,连接双方都能确认对方已经收到了关闭请求,并且所有数据传输都已经完成。
2024-11-15 20:53:08
726
4
原创 Git全攻略:从基础到高级协作,一站式掌握版本控制精髓
欢迎踏入Git的奇妙魔法世界,一场穿梭于代码海洋中的奇幻旅程即将启程!🧚♂️想象一下,你手中握着的不仅仅是一个版本控制系统的钥匙,而是通往无限创意与完美协作的神奇门扉!🌟在这里,每一次commit都是一颗璀璨的星辰,在浩瀚的代码宇宙中留下你的智慧轨迹。🌌而branch,则是你的秘密花园,让你在不受干扰的天地里自由探索、大胆尝试,即使偶尔迷路,merge总能温柔地带你回归主路,拥抱变化,共同成长。🌱别担心,即使你是编程界的小萌新,Git也会用它那温暖而强大的怀抱,一步步引导你学会时间旅行,轻
2024-11-04 07:00:00
722
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
1150
5
原创 揭秘Git合并机制:为何先commit后pull再push,避免代码覆盖的真相
首先,在多人协作的环境中,远程仓库是团队成员共享代码的地方。在提交自己的改动之前,先拉取远程仓库的改动,可以及时发现并解决潜在的代码冲突。,再次 pull 一次是为了防止在你们协商的时候另一个人给又提交了新的一版东西,如果是这样,那上面的流程就再重复一遍,通常没有冲突的时候就直接给你合并了,而并不会把你的代码给覆盖掉。(或Rebase,取决于您的配置):将远程仓库的改动与你的本地改动合并。这位兄台对于pull有个误区,他认为pull会直接将远程仓库的代码覆盖到本地,实则不然。,我们来深入理解一下pull。
2024-10-22 16:30:00
1658
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
1427
原创 C++虚函数表深度剖析
只要一个类中有虚函数,那这个类中就一定会有一张虚函数表,虚函数表中的每一项都是虚函数的地址。这个类的每一个对象都会包含一个虚指针(虚指针存在于对象实例地址的最前面,保证虚函数表有最高的性能),这个虚指针指向虚函数表。
2024-10-20 21:41:15
509
原创 动态内存管理及RAII的简单应用
dll文件是Dynamic Link Library()文件的缩写,它是一种共享库文件,包含了程序所需的代码和数据。与静态链接库不同,动态链接库,使得程序的内存占用更小,同时也方便了程序的更新和维护。程序启动时,系统会将exe主程序依赖的所有dill库文件加载到进程的代码段的内存区中,这些文件里存放的是可执行的二进制机器码,也就是汇编代码。
2024-10-19 11:29:37
781
原创 线程互斥补全和加锁原理
可是此时寄存器内已经是0,它交换之后会做判断,如果是大于0,就执行,等于0,就挂起等待。操作时,以一条汇编指令的形式交换寄存器和内存单元中的数据,将寄存器的1和a来交换。为了方便理解,我们把锁简单理解成包含整形1的一个结构体,在内存单元中。要解决饥饿问题,就要使多线程执行有一定顺序性,也就是线程同步。多线程运行时,一份资源,有进程长期无法拥有,造成饥饿问题。可以定义上面这样的类,自动析构就等于解锁,非常方便。如果这时线程时间片到了,第二个线程过来,也要交换。互斥锁可以是全局的,也可以像上面一样是局部的。
2024-04-19 15:31:55
382
原创 线程互斥及基于线程锁的抢票程序
根据互斥的定义,任何一个时刻只允许一个线程申请锁成功,申请失败的进程在mutex阻塞,本质就是等待。任何时刻,互斥保证只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用。首先把a从内存拷贝到CPU的寄存器,字CPU中完成++操作,再返回内存,不是原子的。可能大家会认为,当线程进入锁,执行锁内代码,这是如果发生切换,还是会产生同样的错误。其实这次不一样了,因为就算时间片到了,发生线程切换,被切换到的线程也没办法访问锁。申请锁本身是原子的,有宝马。就相当于上的线程的密码锁,专属的。
2024-04-18 22:24:33
945
原创 C++的线程
这样,我们学习别的语言,只需要学习接口,因为我们知道底层是一样的。用纯c++的接口创建线程时,在Linux中还是要包含线程库。这说明c++的那些库本质就是pthread原生线程库的封装。在编译链接库时,就会给每一个变量在线程局部存储中开辟空间。__thread可以给每个执行流一个变量。如果不添加-lpthread就会报错。说到底,这样的设计就是为了跨平台性。接下来了解一下线程的局部存储。下面是多线程的一个简单模版。
2024-04-18 13:37:05
417
原创 线程控制及线程底层原理
默认地址空间中的栈由主线程使用,这样,可以保证每一个新线程都可以保存要执行的方法,要传递的参数以及动态运行时的临时变量。同样的,pthread库也是库,在库中实现pthread_create的时候,内部包的就是clone函数。创建线程的时候,在正文代码区,直接跳转到共享区的库里,执行创建线程的函数,然后返回。7、用户栈:线程执行的用户方法栈,用来保存线程当前执行的用户方法的信息。而线程库是共享的,所以,内部要管理整个系统,多个用户启动的所有的线程。
2024-04-17 20:51:26
711
原创 多线程传参以及线程的优缺点
如果计算密集型 线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的 同步和调度开销,而可用的资源不变。linux没有真线程,只有轻量化进程,所以Linux OS只会提供轻量化进程的系统调用,不会直接提供线程创建的接口。编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了。与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多。而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。然后在软件层中,将线程对应成LWP。
2024-04-16 20:16:15
1086
原创 什么是线程?线程和进程谁更弔?
线程较进程更轻量化,调度上来说,pcb切换另一个pcb,地址空间,页表等是不用切换的,只需更换进程运行中寄存器产生的临时数据。线程的本质就是CPU调度的基本代码,Linux内核复用了进程代码,用进程pcb模拟充当线程。操作系统调度的时候,看的也是lwp,判断是主线程还是新线程,看的是lwp是否等于pid。换句话说,线程切换时,不需要切换CPU内部的所有寄存器的数据,而只需更换少部分。cache会对用户操作做出预判,加以缓存,大概率猜对,猜不对也没关系,重新缓存。
2024-04-16 00:58:34
637
原创 从零带你底层实现unordered_map的代码补全(2)
先把代码发出来,大家先看,有什么不懂得都可以私信问我。这块的迭代器是比较复杂,需要仔细看看。有问题题请私信 😘 😘 😘。
2023-12-04 12:41:19
817
4
原创 从零带你底层实现unordered_map (2)
💯 博客内容:从零带你实现unordered_map😀 作 者:陈大大陈🚀 个人简介:一个正在努力学技术的准C++后端工程师,专注基础和实战分享 ,欢迎私信!💖 欢迎大家:这里是优快云,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘哈希/散列:映射,关键字和另一个值建立一个关联关系。哈希表/散列表:映射,关键字和储存位置建立一个关联关系。哈希/散列是一种算法思想,而哈希表/散列表是基于这种算法思想而实现的一种数据结构,这点很容易混淆。上一篇博客介绍了两个解决哈希冲突的方法,
2023-11-28 14:20:30
1339
22
原创 从零带你底层实现unordered_map (1)
它是一个单向的迭代器。为什么专门提到这个呢?因为这是我踩过坑的地方!!单向迭代器压根就不能使用sort函数来排序!std::unordered_map的迭代器类型是ForwardIterator,而不是sort函数要求的RandomAccessIterator,这里不符合。我们要排序的话,还是将unordered_map里存的值,转存到vector里面。然后我们再自定义一个排序方法,对vector进行排序。
2023-11-20 23:08:47
1112
19
原创 并查集模版以及两道例题
上面的时间复杂度最好能有O(1)。实现方式是记忆化搜索,用数组存储好所需结果,需要时就不用再次递归了。这种并查集查找的效率太低,最坏情况的时间复杂度能达到O(N)。我们就针对它优化。上面的时间复杂度最好能有O(1)。实现方式是记忆化搜索,用数组存储好所需结果,需要时就不用再次递归了。来看两个例题巩固一下。How Many Tables(并查集)Problem - 1213 (hdu.edu.cn)题目:Today is
2023-11-06 19:45:15
431
27
原创 多态 多继承的虚表深度剖析 (3)
这么打印,需要注意的是,d是一个Derive类,加一的话会加上一个Derive的大小。我没看到,编译器仍旧是故技重施,欺骗我们的眼睛,我们检测监测不到func3。但是这样的话,就会衍生出一个问题,它自己的虚函数也就是func3放在哪里呢?此时有看起来有3个虚表,其实还是2个。答案是,因为继承了Base1和Base2两个类,所以有两个虚表。上面这种多继承的情况,Derive有几个虚表呢?我们得到结论,func3放到了第一个虚表里面。答案是两张,这种情况就跟普通的多继承没两样。还可以这样写,最聪明的一种写法。
2023-11-05 22:08:45
1394
23
原创 多态 虚函数表深度剖析 纯干货讲解(2)
打开内存监视窗口,我们高度怀疑后面两个地址是被隐藏的两个虚函数的地址。虚函数和普通函数一样,存在代码段,同时将虚函数地址存了一份到虚函数表。第一次编译器出了bug,没有在虚表后标识上0,第二次就好了。终于到了放终结技的时候了,我们可以在打印的时候同时调用函数。上面我们埋下了伏笔,在命令行窗口会打印出来调用函数的信息。经过测试,虚表是储存在常量区的代码段的,跟常量很接近。虚表储存在类的前四个字节,我们就取这四个字节打印出来。并不是这样,监视窗口看到的内容是经过编译器处理的。看不明白的老铁可以看看上面的图。
2023-11-05 18:01:27
245
12
原创 C++ 多态 纯干货讲解 复制可调试(1)
从上面可以看出,C++对函数重写的要求比较严格,但是有些情况下由于疏忽,可能会导致函数名字母次序写反而无法构成重载,而这种错误在编译期间是不会报出的,只有在程序运行时没有得到预期结果才来debug会得不偿失,因此:C++11提供了override和final两个关键字,可以帮助用户检测是否重写。调用指针或者引用指向的对象,指向父类就调用父类,指向子类就调用子类。查找虚函数表中存储的地址,是父类就调用父类,是子类就切割成父类对象。答案是B,容易选成D,需要注意的是,虚函数继承声明,重写实现。
2023-11-04 22:50:11
282
16
原创 关于刷题时使用数组的小注意事项
在Windows下,栈的大小为2M,也就是1024*1024*2 = 2097152个字节。所有我们在程序中声明局部变量时(在栈区),最好不好超过int[200000]的内存变量。总之,当程序需要声明一个超过十万级的变量时,最好放在main函数外面,作为全局变量去使用。不然的话,可能像我上面那样发生栈溢出问题,还以为是代码的思路有问题。对于c语言,一个静态数组能有多大,取决于剩余内存的空间,也就是它所在区的大小;全局数组是存储在内存中的静态区,而局部变量是存储在栈区。
2023-10-20 12:00:53
412
18
原创 (面试)谈谈我对C++面向对象特性的理解
总的来说,面向对象是一种方法,这种方法是用来组织设计和实现的。组织设计就是找到解决问题的思路。实现就是把代码写出来。面向对象关键的核心在于,对象是组织和实现主要关注的东西,而不是过程。
2023-10-07 20:10:03
1041
21
原创 C++的范围for语句详解 附易错实例
在范围for语句中定义的变量,容器或者数组内的每个元素都必须能转换成该变量的类型。实例2:将字符串中所有的大写字母转化成小写字母,将所有的小写字母转化成大写字母。但是有一点要特别注意,刚才举的例子中的变量i实质是数组a中每个元素的。如果仅是修改变量i的值,数组a中的元素的值是不会变化的。范围for语句是C++引入的一个语法糖,例如,下面的代码让数组中每一个元素加三。这么一看还是范围for语句比较简洁。如果要通过变量i修改数组中变量的值,所有的元素都处理完毕后循环终止。让编译器帮助制定合适的类型。
2023-07-09 17:23:20
850
11
原创 C++的auto类型说明符详解 附易错实例
C++里没有越界检测机制,即使正整数的值已经超过了字符串的长度,循环体依旧可以成功运行。所以程序会莫名其妙的输出乱码。而且,即使i从正整数值递减到0,依然会因为刚才解释的原因再次回到那个非常大的正整数值。所以程序是一个死循环。要解决死循环也非常简单。
2023-07-08 21:49:14
1336
45
原创 C++ string中内置的字符串操作和标准库中常用字符处理函数
💯 博客内容:C++读取一行内个数不定的整数的方式😀 作 者:陈大大陈🚀 个人简介:一个正在努力学技术的准前端,专注基础和实战分享 ,欢迎私信!💖 欢迎大家:这里是优快云,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘 😘 😘string中定义了求字符串长度,比较,拷贝等操作,并把他们封装成了一个个函数。
2023-07-07 20:37:46
594
3
原创 C++读取一行内个数不定的整数的方式
💯 博客内容:C++读取一行内个数不定的整数的方式😀 作 者:陈大大陈🚀 个人简介:一个正在努力学技术的准前端,专注基础和实战分享 ,欢迎私信!💖 欢迎大家:这里是优快云,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘 😘 😘。
2023-07-07 16:49:10
1681
35
原创 C++的引用 拷贝赋值和引用赋值
引用是C++里面才有的概念。引用并不是定义了一个新的变量,它只是为一个现存变量起的别名。例如:k就是i的一个别名。定义引用需要注意的地方:来看几个错误的例子巩固一下:但是可以在一条语句中定义多个引用。例如: 拷贝赋值和引用赋值其实就类似于传值和传址的区别。下面来具体看两个代码:运行结果: 运行结果: 第一个是拷贝赋值,第二个是引用赋值。总之一句话,引用即别名。引用并没有创建一个新的变量,只是对原有的变量起了一个新的名字。
2023-07-06 20:12:56
790
4
原创 【PAT B 1010,1011】一元多项式求导 ,A+B和C
设计函数求一元多项式的导数。(注:xn(n为整数)的一阶导数为nxn−1。给定区间 [−231,231] 内的 3 个整数A、B和C,请判断A+B是否大于C。
2023-07-06 16:27:50
670
9
原创 爱玩粥的有福了,带图形界面的明日方舟皮肤的员工管理系统,数据结构期末实训满分。
这个程序底层是easyx图形库,通过在easyx上封装的一个工具类(即输入框、按钮、label等),是在此基础上开发的这个系统。我们期末的数据结构实训已经结束了,我凭借着一手粥批图形界面员工管理系统给老师整不会了,也是顺利得到优秀,接下来就给大家展示一下我一周的成果!
2023-07-03 10:49:42
889
40
原创 【茶话数据结构】查找最短路径——Dijkstra算法详解(保姆式详细图解,步步紧逼,保你学会)
复习到离散数学图论时,想起来这个算法,感觉很有写博客的必要!今天这篇博客就来讲一下查找最短路径的Dijkstra算法。Dijkstra 算法,是由荷兰计算机科学家 Edsger Wybe Dijkstra 在1956年发现的算法,戴克斯特拉算法使用类似广度优先搜索的方法解决赋权图的单源最短路径问题。Dijkstra 算法原始版本仅适用于找到两个顶点之间的最短路径,后来更常见的变体固定了一个顶点作为源结点然后找到该顶点到图中所有其它结点的最短路径,产生一个最短路径树。本算法每次取出未访问结点中距离最小的
2023-06-05 23:50:55
7887
47
原创 【数据结构】插入排序详细图解(一看就懂)
我们将原数组空间看成两个部分,前边是有序部分,后边是无序部分,有序部分我们默认为它就已经是排好序的,在尾部新加入的元素有可能会导致整个有序数组变得无序,因此我们需要进行调整。调整方式就是将新加入的元素进行对比并往前移动,新加入元素和它前边的元素进行对比,如果它比它前边的元素小,则二者互换位置,不断重复这个过程,直到它前边的元素小于它才会停止,这样一来,他就仍然是有序数组。
2023-05-31 11:59:45
2945
57
原创 海量数据中找出前k大数(topk问题),一篇文章教会你
正常思路是把这N个数建成堆,然后 pop k次,即可找到最大的前k个值。但是有些场景,上面的思路解决不了,比如N非常大的情况。假设N是10亿,k是100,就不可能运行出结果。因为如果这样建成堆的话,所占用的空间太大了。10亿个整数需要多大的空间?答案是4GB。4GB的内存啥电脑来了也吃不消,再说100亿,1000亿呢?可见这不是一个可行的方法,咱们另辟蹊径。我们知道,当数据很大时,它不会存在内存上,而是转而储存在磁盘文件里,所以我们的思路就转向磁盘文件。磁盘中能建堆吗?答案是
2023-05-27 23:36:40
2370
47
原创 【数据结构】向上调整建堆和向下调整建堆的天壤之别以及堆排序算法
我们仍旧按最坏的情况来算。最后一层的每个节点都需要向上调整h-1次,光最后一层调整的次数就已经有2^(h-1)*(h-1)次了。光看这一层可以看出差距。上一条讲的向下调整的特点是节点多的层级调整的次数少,是少乘多。而现在讲的向上调整恰恰相反。节点多的层级调整的次数多,是多乘多,这就造成了时间复杂度的巨大差异。同样来计算一下。假设高度为h。F(h)=2^1*1+2^2*2+……+2^(h-2)*h-2+2^(h-1)*(h-1)同样使用错位相减,解得F(h) = 2^h
2023-05-25 20:13:49
1403
36
原创 【重生之我是蜘蛛侠】手把手教你用python爬虫,跟着做就好了
首先要安装bs4这个第三方库。打开pycharm的终端界面,输入pip install bs4即可安装。我之前安装过,所以显示已安装。第三步是导入requests库,没有的话也要安装,步骤和上面的一样,命令变为pip install requests获取豆瓣网页源码先获取网页源码,需要我们先导入requests库。先试试直接获取,看能不能成功。
2023-05-21 22:15:21
1593
50
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人