- 博客(62)
- 收藏
- 关注
原创 5_高并发内存池项目内存优化、页号与Span映射关系使用基数树优化及测试性能与malloc、free比较
按位与操作会将两个操作数对应的二进制位进行与运算(只有当对应的两位都为1时,结果位才为1),这样可以根据页号的某些位信息在第二层页表中定位到特定的页数。由于ThreadCache是线程私有的,因此将它的内存池tcPool设置为静态的,保持全局只有一个tcPool,让所有线程创建自己的ThreadCache的同时,都从着一个定长内存池中申请内存。用数组表示单层基数树,下标对应着页号,数组中的内容是Span的地址BITS对应的是该平台下存储页号占的最大位数,LEHGIH表示的是页数,大小位2^BITS。
2025-01-23 21:47:39
750
原创 4_高并发内存池项目_高并发池内存释放设计_ThreadCache/CentralCache/PageCache回收并释放内存
对各缓存层释放内存的设计,不仅仅是从上一层回收内存,还包括对回收回来的内存怎样处理更有利于下一缓存层的回收,提高效率。线程对象释放内存ThreadCache(1.回收线程释放的内存,2.将多余内存整理归还CentralCache)CentralCache(1.回收ThreadCache释放的内存,2.将多余Span归还给PageCache)PageCache(1.回收CentralCache释放的Span,2.合并,3.并且将内存归还操作系统)1.从。
2025-01-23 21:02:46
1058
原创 3_高并发内存池_CentralCache(中心缓存)和PageCache(页缓存)申请内存的设计
单例模式(Singleton Pattern)是一种常用的软件设计模式,其目的是确保一个类仅有一个实例,并提供一个全局访问点来获取该实例。这个模式在多种场景中都非常有用,特别是在需要控制资源访问,或者管理全局状态信息时。单例模式又分为懒汉模式和饿汉模式,其中懒汉模式较为复杂。在C++中,实现单例模式通常涉及以下几个关键点私有构造函数:将类的构造函数声明为私有,以防止外部代码通过new关键字创建类的实例。私有静态实例变量:在类内部定义一个静态变量来保存类的唯一实例。这个变量是私有的,以防止外部直接访问。
2025-01-21 18:42:01
1370
原创 2_高并发内存池_各层级的框架设计及ThreadCache(线程缓存)申请内存设计
来解决这个问题。测试结果:调试过程中可以看到两个线程互不影响地运行着。从测试结果看,两个线程是同时进行的,并且互不影响。
2025-01-21 18:39:43
1377
原创 1_入门设计一个高并发内存池_从基础开始了解TCMalloc概念_学习设计一个定长内存池
让我们用生活中的例子来解释TCMalloc(Thread-Caching Malloc)的现象:我们可以考虑一个类似于“饮水机、水壶与水杯”的场景,比如我们想要喝水的话,如果没有一些媒介,我们需要直接在水站取水,但是在我们上学时每个宿舍楼都有一个公共饮水机(只考虑一个,不要钻牛角尖),如果每一次想喝水都是直接来喝水,下一次渴了再来喝水,这样饮水机前的队伍大概很拥挤,同时不管对于个人还是群体,喝水的效率都很低。:在内存分配过程中,已经分配给某个进程或对象的内存块中,未被该进程或对象实际使用的部分内存空间。
2025-01-20 21:59:56
637
原创 QT项目_贪吃蛇_详细操作步骤学习
本次做的是QT项目:贪吃蛇我们先来看一下效果图:首先是我们的第一个界面,游戏大厅的界面:接下来是类似于菜单页面的 关卡选择 和 历史战绩 界面:吃一个食物是10分:接下来就是我们的游戏房间界面:分为三种模式:成功创建出一个项目。前面没有截图的部分步骤按照默认的来即可。根据我们分为三个大类的内容创建完整文件和导入需要的资源文件。我们需要创建的 贪吃蛇项目 可以分为:游戏大厅、游戏关卡选择、游戏房间开始游戏。需要导入的资源文件就是 游戏所需的背景图,音效等资源文件。
2024-08-08 15:50:37
1101
原创 Linux中git无法提交,出现不知道身份时的错误,无法检测到有效的电子邮件地址以关联代码的提交
这是因为Git无法检测到有效的电子邮件地址以关联代码的提交。如果问题还是没有解决,那么可以重置邮箱和用户名配置```bashgit config --unset user.emailgit config --unset user.name```我们可以通过下列代码查看邮箱和用户名```bashgit config user.emailgit config user.name
2024-06-19 09:00:00
626
原创 阅读string类文档:类的声明 -成员类型 -成员函数 -迭代器 -容量 -元素访问 -修饰符 -字符串操作 -成员常量 -非成员函数重载
● string类是管理字符的顺序表,字符串是表示字符序列的类。● 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。● 通过图一,我们可以看到typedef basic_string string; ,string 类是 basic_string 类模板的实例化,string在底层实际是basic_string模板类的别名。● 不能操作多字节(在某些编码系统(如UTF-8)中,一个字符可能由多个字节组成。对于这样的字符,如果字符串操作不当,可能会导致字
2024-06-19 08:45:00
1689
原创 再探构造函数-Static成员-友元-内部类-匿名对象
再探构造函数-Static成员-友元-内部类-匿名对象当对象在创建时获得了一个特定的值,我们说这个对象被初始化(initialized)了。用于初始化变量的值可以是任意复杂的表达式。当一次定义了两个或多个变量时,对象的名字随着定义也就马上可以使用了。因此在同一条定义语句中,可以用先定义的变量值去初始化后定义的其他变量。声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。
2024-05-14 13:15:56
854
原创 类的6个默认成员函数:构造函数-析构函数-拷贝构造函数-赋值运算符重载-const成员函数-取地址及const取地址操作符重载
如果一个类中什么成员都没有,简称为空类。空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。每个类都分别定义了它的对象被初始化的方式,类通过一个或几个特殊的成员函数来控制其对象的初始化过程,这些函数叫做构造函数(constructor)。构造函数的任务是初始化类对象的数据成员,无论何时只要类的对象被创建,就会执行构造函数。全缺省参数的声明和定义分离时。定义一个日期类Date:对于Date类,可
2024-05-14 13:15:20
662
原创 类与对象:实例化,类的概念,访问限定符,封装,作用域,类对象模型,this指针
在C++中,我们通过定义一个类(class) 来定义自己的数据结构。一个类定义了一个类型,以及与其关联的一组操作。类机制是C++最重要的特性之一。实际上,C++最初的一个设计焦点就是能定义使用上像内置类型(内置类型(built-in type) 由语言定义的类型,如int)一样自然的类类型(class type)。C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如:之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;
2024-05-04 12:30:21
872
原创 C++引用&(引用做参数,返回值;传值,传引用做函数参数或返回值类型)-内联函数( inline 修饰的函数,替换宏)-auto关键字(自动推算变量类型)
使用auto修饰的变量,是具有自动存储器的局部变量auto不再是一个存储类型指示符,而是作为个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。return 10;auto b = a;// typeid可以看变量的类型//auto e;无法通过编译,使用auto定义变量时必须对其进行初始化return 0;[注意]
2024-05-04 12:28:58
1278
原创 C++的初步知识——命名空间,缺省参数,重载函数
命名空间中可以定义什么?// 1. 正常的命名空间定义// 命名空间中可以定义变量/函数/类型int val;//2. 命名空间可以嵌套int a;int b;int c;int d;//3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。// ps:一个工程中的test.h和上面test.cpp中两个N1会被合并成一个// test.h注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。
2024-04-21 18:28:34
1014
原创 二叉树链式结构的实现-二叉树的前序 中序 后序 层序遍历
前序: 根 左子树 右子树 --》先根中序:左子树 根 右子树 --》中根后序:左子树 右子树 根 --》后根层序:一层一层访问。
2024-04-21 18:26:12
294
原创 堆排序-升序和降序_TopK-N个数找找最大的前K个
堆排序即利用堆的思想来进行排序,总共分为两个步骤:1.建堆升序:建大堆降序:建小堆;2.利用堆删除思想来进行排序。TopK-N个数找找最大的前K个:1.将前K个数拷贝进新创建的空中中,建小堆;2.后N-K个数与堆项元素一一比较,比堆项元素大,就调换他们的位置;3.前K个数保持小堆,需要向下调整调换过位置;4.最后的小堆的值就是前K个数。
2024-04-12 19:29:56
388
原创 二叉树-认识树及堆,堆的实现
树是一种非线性的数据结构,是n(n≥0)个结点的有限集。当n=0时,称为空树。** 一颗N个结点的数有N一1条边。**** 树适合于表示具有层次结构的数据。**
2024-04-12 14:18:23
770
原创 有效的括号--如果字符串没有左括号,或者字符串是右括号为开头,则存在括号不匹配和顺序不正确的情况公字符串无效
有效的括号--如果字符串没有左括号,或者字符串是右括号为开头,则存在括号不匹配和顺序不正确的情况公字符串无效。判断完字符串中元素,判断栈中是否有留存的括号。如果有,则没有匹配成功;如果没有,则括号均匹配成功。此时为空ret则为真,否则ret就为假。
2024-04-06 19:50:22
202
原创 用栈实现队列-使用两个栈来实现队列,则使我们插入的元素依照先入先出原则即可
1、创建两个栈,我们知道栈的原则是“先进后出”,而队列则是“先进先出”的原则。使用两个栈来实现队列,则使我们插入的元素依照先入先出原则即可.2、想要1先出来,就需要将1.上面的元素转移到栈2中,且栈2空间必须是无元素的。当栈1只剩下元素1时,将1弹出,其余元素依次使用此方法。直到所有元素弹出。3、根据栈的先入后出,后入先出的原则。栈2的元素可以直接弹出,无须再导入栈1.由此,基本使用两个栈实现队列。接下来,进行完善。
2024-04-06 09:18:42
276
原创 栈、队列-栈的概念及结构/栈的实现/栈的顺序存储结构-队列的概念及结构、队列的实现(链式存储结构))
一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。栈的插入操作叫做进栈/压栈/入栈,:栈的删除操作叫做出栈。栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表, 队列具有先进先出FIFO(First In First Out)队列也可以数组和链表的结构实现,使用链表的结构实现更优,因为如果使用数组结构,每次元素出队列时都是从数组头出数据,再依次将数组上的元素往前移,效率会比较低。
2024-04-05 17:09:09
495
原创 带头双向循环链表,顺序表和链表的比较
单链表结点中只有一个指向其后继的指针,使得单链表只能从前往后依次遍历,要访问某个结点的前驱(插入、删除操作时),只能从头开始遍历,访问前驱的时间复杂度为O(N)。为了克服这个缺点,引入了双链表。
2024-04-05 13:24:08
527
原创 学习408之数据结构--链表-单链表的增删查改的实现-如何解决顺序表增容后空间浪费问题?
链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。思考:如何解决以上问题呢?
2024-03-08 09:00:00
1029
原创 学习408之数据结构--线性表-顺序表 学会动态顺序表的创建
首先线性表是一个序列,元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都前驱和后继。其次,线性表强调是有限的,其中的元素是有限的。比如,要实现两个线性表集合A和B的并集操作。即要使的集合A=A并集B。也就是将存在于B中,不存在于A中的元素插入进集合A中。
2024-03-04 09:30:00
877
原创 每天一道练习题-删除有序数组中的重复项
因为是递增数列,所以一个数比个数大(非严格递增数列,也是这种思路)将arr通过函数传递至nums所以我们使p[0] - nums[0];指针p中存放的就一定是严格的递增数列,相当于刚除重复部分数字。所以将nums中的元索与p中的元素进行比较,nums[i]大于p[0],则使p[1] - nums[i];而这个变化可能是多次的因此p[j] - nums[i]:需要注意,进行到这一步时,因为我们在此前就为p[0]赋值nums[0]了
2024-02-29 10:00:00
421
原创 学习408之数据结构--算法,时间复杂度和空间复杂度
通常,我们都使用“时间复杂度”来指运行时间的需求,使用“空间复杂度”指空间需求。当不用限定词地使用“复杂度”时,通常都是指时间复杂度。
2024-02-27 10:30:00
2649
原创 初学学习408之数据结构--数据结构基本概念
数据 : 是描述客观事物的符号,是计算机中可以操作的对象,是能被计算机识别,并输入给计算机处理的符号集合。数据不仅仅包括整型、实型等数值类型,还包括字符及声音、图像、视频等非数值类型。
2024-02-26 13:11:02
1070
原创 通讯录代码
/ //查找联系人assert(pc);printf("请输入要查找联系人的名字:>");i < pc->sz;printf("该联系人不存在于通讯录\n");return -1;//函数的定义//// 初始化通讯录assert(pc);pc->sz = 0;//初始化//增加联系人assert(pc);printf("联系人已满,无法添加\n");return;printf("请输入添加联系人名字:>");
2024-02-20 15:15:23
425
原创 字符串旋转:写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。例如:给定s1 = AABCD和s2 = BCDAA, 返回1
写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。例如:给定s1 = AABCD和s2 = BCDAA, 返回1给定s1 = abcd和s2 = ACBD,返回0.AABCD左旋一个字符得到ABCDAAABCD左旋两个字符得到BCDAAAABCD右旋一个字符得到DAABC。
2024-02-05 12:48:35
727
1
原创 字符串左旋
内容:实现一个函数,可以左旋字符串中的K个字符。ABCDEF左旋一个字符可以得到BCDEFA。ABCDEF左旋两个字符可以得到CDEFAB。
2024-02-04 18:10:13
573
原创 C语言输出水仙花数——有举例错误代码
水仙花数(Narcissistic number)是一个具有三个数字的整数,且其每个数字的三次幂之和等于它本身。水仙花数(Narcissistic number)也被称为超完全数字不变数(pluperfect digital invariant, PPDI)、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数(Armstrong number)。例如,153是一个水仙花数,因为1^3+5^3+3^3=1+125+27=153。例如,111、222、333等数字不被认为是水仙花数,因为它们由相同的数字组成。
2024-02-02 16:30:00
723
原创 malloc()和free()
free()函数的参数是之前malloc()返回的地址,该函数释放之前malloc()分配的内存。• 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者来决定。• 如果参数 string 指向的空间不是动态开辟的,那free函数的行为是未定义的。• 如果开辟失败,则返回⼀个 NULL 指针,因此malloc的返回值⼀定要做检查。• 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。• 如果开辟成功,则返回⼀个指向开辟好空间的指针。
2024-01-26 09:00:00
734
原创 大小端字节序和字节序判断
其实超过一个字节的数据在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分为大端字节序存储和小端字节序存储,下面是具体的概念:大端(存储)模式:是指数据的低位字节内容保存在内存的高地址处,而数据的高位字节内容保存在内存的低地址处。小端(存储)模式:是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容保存在内存的高地址处。调试的时候,我们可以看到在a中的 0x11223344 这个数字是按照字节为单位,倒着存储的。
2024-01-25 14:53:44
473
原创 C语言学习NO.14-字符函数(四)-字符串查找,strstr函数,strtok函数
• strtok函数找到string中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。• strtok函数的第一个参数不为 NULL ,函数将找到string中第一个标记,strtok函数将保存它在字符串中的位置。• strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。• 如果字符串中不存在更多的标记,则返回 NULL 指针。
2024-01-07 09:30:00
1409
原创 C语言学习NO.13-字符函数(三)-strncpy,strncat,strncmp长度受限制的字符串函数
•使用时需要包含头文件• 将源字符串的前num个字符复制到目标。如果源C字符串的末尾在复制num个字符之前找到'\0',剩下自动记0,直到总共写入了num个字符。•拷贝num个字符从源字符串到目标空间。•如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。•使用时需要包含头文件• 将源的前num个字符追加到目标,再加上一个终止的null字符。(将来源指向字符串的前号码个字符追加到目的地指向的字符串末尾,再追加一个 \
2024-01-06 16:00:00
1591
原创 C语言学习NO.12-字符函数(二)-strcpy,strcat,strcmp长度不受限制的字符串函数
• 源字符串必须以 '\0' 结束,会将源字符串中的 '\0' 拷贝到目标空间。当源字符串空间大于目标空间时,使用strcpy函数会有怎样的结果?存在错误,自身附加自身的字符串时,字符串的'\0'很容易被覆盖。• 注意strcpy需要包含的头文件是 如下例,字符中的'\0'也会同样被赋值进目标空间。• 目标空间必须足够大,以确保能存放源字符串。•strcpy函数返回的是目标空间的起始地址。• 目标空间必须可修改。
2024-01-06 14:00:00
698
原创 C语言学习NO.11-字符函数strlen,strlen函数的使用,与三种strlen函数的模拟实现
如果用str++ 先使用 后自增 这里的使用表示传参 所以就只会把a的地址传进去 就不符合我们的预期了。strlen的返回值类型是无符号型,无符号型-无符号型还是无符号型,因此最后的结果一定是大于0的。在程序进行中,每次进入新阶段前,str的地址发生了改变,但是进入新阶段后,仍是原地址。所以这里如果这样写 传进去的那个地址值就还是原本的指向。• 参数指向的字符串必须要以 '\0' 结束。str所指向的地址发生了变化。为何输出的结果与预期的不同?二、使用++str的调试结果。一、str++的调试结果。
2024-01-05 17:36:23
1373
原创 描述输入两个升序排列的序列,将两个序列合并为一个有序序列并输出。数据范围: 1≤n,m≤1000 , 序列中的值满足 0≤val≤30000 输入描述:输入包含三行,第一行包含两个正整数n
第一行包含两个正整数n, m,用空格分隔。n表示第二行第一个升序序列中数字的个数,m表示第三行第二个升序序列中数字的个数。输出为一行,输出长度为n+m的升序序列,即长度为n的升序序列和长度为m的升序序列中的元素重新进行升序序列排列合并。数据范围: 1≤n,m≤1000 , 序列中的值满足 0≤val≤30000。输入两个升序排列的序列,将两个序列合并为一个有序序列并输出。第二行包含n个整数,用空格分隔。第三行包含m个整数,用空格分隔。
2023-12-30 18:38:14
461
原创 C语言学习NO.7-函数(二)函数递归
程序调用自身的编程技巧称为递归( recursion),递归函数一定要有结束条件,否则会产生死递归,导致栈溢出(Stack overflow)。//main函数中又调用了main函数return 0;} //程序会一直打印 Hello递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,使用递归可以在解决一些复杂问题时将问题简单化,降低编程难度。递归的主要思考方式在于:把大事化小递归就是递推回归的意思。
2023-12-28 15:12:54
1061
原创 C语言学习NO.9-指针(一)内存和地址,指针变量,指针变类型的意义,const修饰指针,指针运算,野指针,assret断言,指针的使用和传址调用
称为“直接访问”。如**printf(“%d”,i);
2023-12-23 17:02:56
978
原创 C语言学习NO.10-指针(二)数组名的理解,使用指针访问数组,一维数组传参的本质,冒泡排序,二级指针,指针数组,指针数组模拟二维数组
同理arr[i] 应该等价于 *(arr+i),数组元素的访问在编译器处理的时候,也是转换成首元素的地址+偏移量求出元素的地址,然后解引用来访问的。这个代码搞明白后,我们再试一下,如果我们再分析一下,数组名arr是数组⾸元素的地址,可以赋值给p,其实数组名arr和p在这里是等价的。parr[i]是访问parr数组的元素,parr[i]找到的数组元素指向了整型一维数组,parr[i][j]就是整型一维数组中的元素。现在在函数内部计算数组的元素个数,我们可以吧函数传给一个函数后,在函数的内部求数组的元素个数。
2023-12-23 16:51:15
883
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人