- 博客(29)
- 收藏
- 关注
原创 C++:关于反向迭代器的学习分享
反向迭代器的begin位置对应容器的end位置,反向迭代器的end位置对应容器的begin位置,为了方便理解,下图是一个list的begin位置以及end位置,那么相对于的就是list的反向迭代器的rbegin位置以及rend位置。那么反向迭代器的operator++()与 operator--()函数会调用正向迭代器的operator--()与operator++(),并且内部都是对正向迭代器的函数复用操作。那么反向迭代器的初始化其实就是通过传入的正向迭代器的参数对反向迭代器里的it进行初始化。
2024-09-03 19:16:28
586
原创 C++:模拟实现list
上篇文章简单介绍了list的接口使用,那么这篇文章将通过模拟实现list以及常用接口来更好的去理解list类,观看本章前将默认读者对链表的数据结构有初步的了解。list在库里是一个带哨兵位的双向循环的链表结构,并且list是一个类模板并不是一个指定的类型,所以在模拟实现时需要写成模板。
2024-08-31 11:35:52
1284
原创 C++:list篇
我们可以看到,当erase后如果在对it迭代器进行操作,vs则会进行强制检查(根据编译环境不同,处理环境也不相同),则不允许再继续使用,如果想继续使用的话,C++同样也给出了方案,可以看到erase会返回一个迭代器,而返回的迭代器就是下一个链表的位置。那么从上面的begin与end可以看出,使用迭代器遍历list,仅仅只需要解引用迭代器以及++迭代器就能取得我们想要的值与让迭代器走向下一个节点,那么有没有想过一个问题,list的迭代器与vector这种类似数组的迭代器底层是否是一样的呢?
2024-08-27 21:01:50
1466
原创 C++:vector篇
从上图可以看出,一开始创建了vector<int>类型的v1,并且通过push_back函数(这个函数后面会说明),对v1进行插值,接着又创建了v2并以v1为拷贝对象使用拷贝构造,使用范围for打印结果可以看出,v2把v1的数据进行了拷贝,并同时也进行了扩容的操作。从上图看到,在vector中的成员变量不像之前的sting,他采用了三个类模板的指针变量,_start(开始) , _finish(完成), _end_of_storage(结尾的存储位置),分别对应了str的指针,top以及capacity。
2024-08-24 10:46:01
731
原创 C++:模拟实现string
为了更好的理解string底层的原理,我们将模拟实现string类中常用的函数接口。为了与std里的string进行区分,所以用命名空间来封装一个自己的strin类。
2024-08-19 16:51:43
1010
原创 C++:string类篇
从上图可以看到,我们创建了一个string类的iterator(迭代器)变量it,并用s1.begin()函数的返回的迭代器值赋值给it,接着就类似指针的操作,将it解引用并循环输出值。2.string& append (const string& str, size_t subpos, size_t sublen):截取string对象中的一部分内容到自身内容后.1.string& append (const string& str):使用已有的string对象数据拓展自身对象数据。
2024-08-19 11:45:08
939
原创 C++:初阶模板
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟< >,然后将实例化的类型放在< >中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。从上图可以看到,模板仅仅至少充当一个中介的角色,当给模板传入实参,编译器会根据实参的类型去推演自动生成对应类型的函数,可以从下图的汇编码能更好的证明这一点。可以看到如果按照之前的方式仅仅通过访问限定符去定义类是完全不行的,在 C++ 中,模板类的成员函数定义必须指定模板参数,因为这些成员函数的定义是在模板类的上下文中进行的。
2024-08-14 22:25:23
489
原创 C++:内存管理
通过任务管理器可以看到此时vs的运行窗口直接占用了2G左右的内存就不动了,说明此时堆上已经没有空间申请,当程序继续运行也没有发生而是捕捉到了编译器抛出的异常,输出bad allocation(糟糕的分配),提示程序员问题的出处。int* p1 = (int*)malloc(sizeof(int)):因为C++是C的延申,所以C++兼容C语言,在C++里也可以使用C语言的代码,malloc从堆中分配了一个int类型的空间,这个大家都熟悉.除非给每个对象都传入参数。p2指向的空间是通过new分配来的。
2024-08-13 09:27:10
915
原创 C++:类与对象(中)
需要释放的资源成员都是自定义类型,不需要写析构,前提是自定义类型里写了析构函数,编译器会自动调用自定义类型成员的析构函数,这点与上面的构造函数类似。这里就需要额外创建一个对象,先保存d1的值,再让d1+1,并且因为这个额外的对象是一个局部对象,如果传引用返回就会造成野指针现象,必须穿值返回。,那么此时传d2进成员函数Print就不会发生报错,权限也只是平移,那么在传d1的时候也同样不会报错,权限可以被缩小这种机制有助于增强代码的安全性和可读性,确保对象在被标记为const时保持不变。
2024-08-10 09:00:15
1334
原创 C++:类和对象(上)
A1类的对象a与A2类的对象b通过sizeof计算出它们的大小都为1,这是为了确保每个对象在内存中占有独立的空间,即使是空类也需要有独特的地址。此时将代码进行调试并转到反汇编指令时发现,d1.Init()与 d2.Init()都call向同一块空间,那么也就说明d1的成员函数与d2的成员函数是共用的,所以类成员函数的是存放在一个公共的代码区域段的地方,那么这样做也是为了节约空间。类中的函数称为类的⽅法或者成员函数。类同样拥有自己的域,类的所有成员都在类的作⽤域中,同时类域不影响变量⽣命周期。
2024-08-06 18:19:45
1017
原创 C++篇:入门(2)
而a的值被修改为20,可以看出在b=c这步操作里,是将c的值赋到了别名b中,而b的本体其实是a,修改b的值同时也是修改a的值。然后,通过返回k的引用来返回一个整型的引用,而因为k是函数内的局部变量,而当函数进行执行完则进行销毁,此时k的引用指向一个已经不存在的内存位置,使用引用进行返回相当于跨过了将值传递给临时变量的步骤。因为返回的是参数,而函数在返回的时候并不是直接返回值,而是会通过一个临时变量将k的值存储起来可能是寄存器的存储,当函数栈帧销毁时,再把存储的值赋给ret1,此时ret1的值是安全的。
2024-08-03 19:41:01
1137
原创 C++篇:C++入门基础(1)
上图代码,小编创建了一个int类型的全局变量rand,并在主函数里尝试输出rand,此时可以看出函数在编译的时候就进行了报错,给出的理由是rand重定义,表明rand在这里是一个函数,而自己又给rand定义成了一个int类型的全局变量,那么在c++的编译是时候是不会通过的。如上图,在函数Add中定义了三个形参a,b,c。C++⽀持在同⼀作⽤域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同,通俗的来说,函数重载就类似于,有很多个同名同姓的人,但每个人都是不同的个体。
2024-08-02 13:43:42
1266
原创 数据结构——排序(C语言版)
a[hole] = a[left]:将找到的大于基准值的元素移到之前坑洞的位置,即hole所指向的位置。这样,prev指向的是当前已经处理好的小于基准值的部分的最后一个元素的位置。希尔排序法的基本思想是:先选定⼀个整数(通常是gap = n/3+1),把 待排序⽂件所有记录分成各组,所有的距离相等的记录分在同⼀组内,并对每⼀组内的记录进⾏排序,然后gap=gap/3+1得到下⼀个整数,再将数组分成各组,进⾏插⼊排序,相当于在插入排序之前对原数据进行一个预排序,当gap=1时就相当于 直接插⼊排序。
2024-07-31 13:43:08
941
原创 数据结构——链式二叉树(C语言版)
根据顺序,从根开始并没有先输出值而是先开始递归根的左子树,从上图的左子树的递归展开图中,当节点递到3的左子树(NULL)时,先输出NULL接着开始归,重新归到3节点时输出3,接着递归3的右子树(7),并重复步骤,当1的左子树递归完后就输出1节点的值并执行递归1的右子树。想要计算二叉树的深度,就要计算根的左子树与右子树的深度,将左子树的深度与右子树的深度进行比较,并返回较大值,如上图,通过递归展开,会得知左子树的深度为3,右子树的深度为2,最终返回左子树的深度+1,所以上图二叉树的深度为4。
2024-07-27 23:23:54
646
1
原创 数据结构——堆(C语言版)
第三步:在循环里创建一个if语句,如果父亲节点的值小于孩子节点,那么就进行向上交换,孩子变父亲,父亲变孩子,然后将父亲位置赋值给孩子,继续向上找父亲节点位置进行循环判断是否交换,如果不需要交换(父亲节点>孩子节点)就直接退出循环。从上图可以发现,在堆顶(数组下标为0)的位置中存放的数据,是这个堆中最大的值,并且堆中某个结点的值总是不大于其⽗结点的值,我们将这种堆称之为大根堆。从上图可以看出⼆叉树不存在度⼤于 2 的结点 ,并且⼆叉树的⼦树有左右之分,次序不能颠倒,因此,二叉树又是一个有序树。
2024-07-22 21:50:03
887
1
原创 数据结构——栈与队列(C语言版)
一:栈栈的概念:栈(Stack)是一种常见的数据结构,它基于后进先出( Last In, First Out, LIFO)的原则工作。这意味着最后进入栈的元素最先被移除,而最先进入栈的元素最后被移除。栈通常有两个主要操作::将元素添加到栈的顶部。:从栈的顶部移除元素。栈的特性决定了:栈只能访问栈顶的数据,并遵循着先入后出的原则,如果像访问栈底数据,只能将栈上剩余的数据全部依次弹出,不能去遍历,否则会破坏栈的性质。
2024-07-18 13:50:41
920
1
原创 浅谈力扣138题——随机链表的复制
可能有读者会有疑惑,那可不可以直接遍历原链表节点的val值,让原链表random指向的节点中的val值去匹配新链表节点random指针的指向的节点中val值。因为要返回的是全新的的链表,链表中的每个节点都是需要去申请来的,所以,原链表节点中的random指针指向的节点,与新链表的节点中的random指向的节点是毫无关联的。,唯一相同的只有他们的next指针都是指向下一个链表,所以新链表与原链表是毫无关联,不能单纯的通过原链表的random节点去匹配新链表的random节点。这里一定要理解,新链表的地址。
2024-07-13 00:09:09
696
原创 关于力扣——环形链表|| 的一些见解
通过题目给出的示例图,我们可以得知,链表的尾节点指向前面链表的其中某一个节点,这个节点可以在头可以在尾也可以在中间,而我们需要找到链表尾节点的下一个节点及入口循环链表的入口点。当slow走到入口点时,假设此时fast的位置在图中标记的地方,这里需要知道由于slow只走一步并且fast只走两步,所以slow。一个指针从起始点开始走,一个指针从相遇点开始走,这两个指针会在入口点相遇。一个指针从起始点开始走,一个指针从相遇点开始走,这两个指针会在入口点相遇。,这道题的意思是要找出环形链表的入口点。
2024-07-11 14:41:34
478
2
原创 数据结构——顺序表(C语言版)
顺序表(Sequential List)是一种基本的数据结构,用于存储线性表(元素之间有序排列的数据集合)。顺序表的特点是元素在内存中连续存储,每个元素占用固定大小的存储单元,通过元素在内存中的相对位置来确定其逻辑顺序。从概念中可以看出顺序表和数组是很相似的顺序表与数组的区别:顺序表与数组的相同点都是在内存中连续存储,但顺序表并非是数组,只是顺序表的底层和数组一直这里简单画了一个图,我们将数组看作是一个普通衣柜,顺序表看作是一个折叠衣柜。
2024-07-11 00:38:30
888
原创 C语言关于预处理的基础介绍
在这个表达式中,(5++) 和 (4++) 会被进行比较,比较完再经行后置++操作,这里5与4先进行比较,接着5++变成了6,4++变成了5,而因为5>4,返回的是第二个表达式(a),而a这里会被替换成(6++)因为刚才5已经变成6了。从上图示例可以看出 我的test.c的文件只有#include"head.h"的文件包含,编译器会在源文件下的目录进行查找头文件,如果该文件未找到,编译器就会像查找库函数头文件一样在标准位置下查找头文件。可以看到a和b的输出是相似的,此时可以想到是不是可以用函数来进行简化。
2024-06-06 14:41:18
1980
原创 C语言编译与链接的基础知识
通过上图示例,小编在一个项目里面创建了两个.c的文件,在链接的过程中,text文件里的main标识符与Add标识符会进行符号解析,将这两个标识符解析成地址后形成一个符号表,又因为extern Add 声明了Add函数是一个外部函数 所以Add的地址为0地址,接着解析add文件里的Add标识符,形成符号表,最后将两个符号表进行合并,发现在text文件里声明的Add标识符刚好与add文件里的Add标识符对的上,那么这两个标识符地址就进行重定位,最终合成合成了一个新的符号表,那么程序就会继续执行下去并不会报错。
2024-06-05 19:15:41
1673
原创 C语言关于文件的一些基础知识
从上示例可以看到,刚才将字母a到z放入文件后,这次将pf的指针再次指向刚才的文件,并且用”r“读取的形式来操作文件,定义了变量ch,通过while循环,运用fgetc函数每一次读取得到文件中单个的数据,并且打印出来。文件指针是一个特殊类型的指针,用于跟踪程序中打开的文件。fseek(pf,2,SEEK_SET)表示将文件的光标从pf所指向的文件中的文件开头(SEEK_SET)开始向右偏移两个位置,此时光标指向了数据c的位置,再通过变量ch将数据c打印出来,此时文件光标已经指向了下一个数据d的位置。
2024-06-03 00:43:40
1623
原创 想要初步了解指针?看这篇就够啦!
从上图示例可以看到 arr的地址为00BEFE98,将arr+1及加四个字节的长度,那么&arr+1与arr的首地址地址相差20个字节,得到数组末尾的地址,而数组指针p取得arr的地址后,将p+1,得到的也是数组末尾的地址。从上图可以看出:ptr指针一开始指向的是arr首元素的地址,将ptr+2,越过八个字节,得到数值3的首元素地址,接着用“ * ”操作符,将int类型的指针解引用访问后4个字节的长度,得到数值3。换句话说,二级指针存储的是一个指针变量的地址,而这个指针变量本身又存储着另一个变量的地址。
2024-05-28 20:36:05
1033
原创 C语言——循环分支语句
if是最基本的分支语句,它允许根据一个条件来选择性地执行代码块a==1是一个表达式,当其结果为真(及a真的等于1)时,会执行if后面的代码块;否则,会执行else后面的代码块。switch允许根据一个表达式的值选择不同的执行路径。它通过将表达式的值与多个case标签进行比较,从而决定执行哪个代码块。switch语句的基本语法如下:当switch语句的表达式匹配到某个case标签时,程序会执行该case标签对应的代码块,并且继续执行后续的case标签对应的代码块,直到遇到break语句或者。
2024-05-26 11:57:40
322
原创 C语言字符串函数介绍
上图为模拟实现memcpy函数的示例,可以看出memcpy函数中sourc指针将一个字节一个字节的拷贝内存数据到destination指针中,将destination指针与source指针强制转换成char*类型,char*类型的指针每次访问一个字节,这样就能适用于多种类型数据的拷贝。如上图示例 在arr1的字符串中包含了arr2的字符串,那么返回值介绍arr1字符串中首次出现arr2字符的位置,如果没有找到arr2字符则返回空指针NULL.第一个字符串大于第二个字符串,返回大于0的数字。
2024-05-25 18:20:25
879
原创 C语言—关于整数与浮点数在内存中的存储方式
b的值为-1转换成二进制后为 10000000 00000000 00000000 00000001 因为是负数所以最高位为1,转换成反码则是 符号位不变其他位按位取反,得到11111111 11111111 11111111 11111110 ,将反码加1得到补码11111111 11111111 11111111 11111111。:用来表示浮点数的有效数字部分。尾数位存储的是二进制小数的小数部分,通常被标准化为形如1.xxxxxxx的形式,其中小数点左边的第一个数字总是1,因此不需要存储。
2024-05-25 13:49:27
805
原创 C语言结构体知识
通过图可以看出,结构体成员a的类型是int,恰巧它是第一个成员 所以它的位置在偏移量为0的位置,a的起始位置为0 又因为a为int类型 int占4个字节与默认对齐数8进行比较 得到的较小结构为4 所以a占用的内存为0-3的空间(共四个字节)。这里将 a与c的位置进行调换可以看出 char类型c为偏移量为0的位置占用1个字节 a为int将占用四个字节的位置 而a的对齐数为4 需要从4的倍数开始对齐 所以浪费1-3空间 从4开始占用。是的结构体也存在内存大小,那么结构体的内存大小是如何计算的呢?
2024-05-24 19:16:54
700
1
原创 萌新的第一篇博客
本萌新目前为福建的一所大专准大一计算机网络新生原在技校浑浑噩噩玩了一年多后因中途的一些变故充分让我认识到学习的重要性,清楚自己想要什么想学什么,经过努力考上大专,我深刻认识到计算机这门学科是个深且难的专业,但我已经做足准备来攻读这门专业,目前已经将c语言学完。掌握基础编程语言后,多看有关编程的书,多刷题,多看大牛写的代码,不做井底之蛙,充分学习后开始自己找开源项目先跟着做到最后自己独立完成。目前没有最想进的IT公司 我深刻认识到我的学历不足所以我将要通过专升本来提升自己学历从而使自己拥有更多的选择。
2024-05-24 11:58:41
203
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人