- 博客(49)
- 收藏
- 关注
原创 关键点(c++,Linux)
一旦一个类内的成员函数被声明为静态的(static),那么就可以不创建该类的任何对象实例,直接通过类名和作用域解析运算符(::)来访问这个函数。所以私有静态变量也是可以在类外初始化的。静态成员函数也正是为管理和操作这些“类级别”的静态数据而设计的。普通(非静态)成员函数在被调用时,编译器会隐式地传递一个指向当前调用对象的指针,即。指针,函数才能知道它要操作的是哪个特定对象的数据。,它自然就无法确定要访问哪个对象的非静态成员。类内的静态成员变量的初始化要在类外,注意。函数内部的局部变量是线程私有的。
2025-09-13 23:12:27
349
1
原创 Linux线程控制
•与线程有关的函数构成了⼀个完整的系列,绝⼤多数函数的名字都是以“pthread_”打头的• 要使⽤这些函数库,要通过引⼊头⽂ <pthread.h>• 链接这些线程函数库时要使⽤编译器命令的“-lpthread”选项。
2025-08-15 19:58:56
696
原创 Linux中的线程(Lightweight Processes - LWP)
Linux通过轻量级进程 (LWP)和强大的`clone()`系统调用实现了线程。现代Linux使用NPTL库,采用**1:1模型**(一个用户线程对应一个内核LWP)。线程共享进程的地址空间、文件描述符等资源,但拥有独立的栈、寄存器、线程ID和调度状态。POSIX Threads (`pthreads`) API是创建和管理线程的标准接口。理解线程的核心在于理解其资源共享模型和由此产生的同步需求。线程提供了高效并发和资源共享的能力,但也带来了编程复杂性和同步挑战。
2025-07-26 15:41:12
724
原创 虚拟地址-物理地址
如果在没有虚拟内存和分⻚机制的情况下,每⼀个⽤⼾程序在物理内存上所对应的空间必须是连续的,如下图:因为每⼀个程序的代码、数据⻓度都是不⼀样的,按照这样的映射⽅式,物理内存将会被分割成各种离散的、⼤⼩不同的块。经过⼀段运⾏时间之后,有些程序会退出,那么它们占据的物理内存空间不可以被回收,导致这些物理内存都是以很多碎⽚的形式存在。怎么办呢?我们希望操作系统提供给用户的空间必须是连续的,但是物理内存最好不要连续。
2025-07-25 18:24:26
1060
原创 c语言中指针深刻且简单的理解
答案是显然的,稍加思考我们就知道既然存放的是内存地址,那么指针申请出来存放内存地址的空间就应该正好能存下所有的内存地址,也就是可以给所有的内存空间编号。,注意是指向的空间大小不同。不同的指针类型指向的空间是不同的,例如:int* 指向的空间是4字节的,char*的指针指向的空间是一字节的。你对int*的地址解引用得到的是地址后跟着的4字节的内容,你对char*的地址解引用得到的是地址后1字节的内容。int**:指向类型是int*为八字节(默认为64为机器),所以就是:该指针的内容为某八字节空间的首地址。
2025-07-06 21:16:44
210
原创 c++中的左值和右值
右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引用返回)等等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。右值引用就是对右值的引用,给右值取别名核心特性:无身份(Identity):通常是临时对象,无持久内存地址(不可取地址)。短暂存在:生命周期仅限当前表达式。(但是被右值引用之后就延长了生命周期,延长至右值引用变量的作用域结束)可被移动(Movable):资源可被“窃取”(C++11 起)。通常没有变量名。常见右值。
2025-07-04 17:11:08
746
原创 c++迭代器的思想
因为STL容器的需要,迭代器抽象了“位置”的概念,并定义了如何在容器元素间移动和访问元素。而迭代器正好可以对不同的容器进行相应的适配,实现不同容器的迭代器类型,对外表现的使用接口还是一致的,使用上就简单了。(generalized pointer),一般来说迭代器都是将指针进行了封装,在容器类型的基础上实现统一接口,隐藏容器内部结构。对于不同的容器有不同的容器适配,容器中只需要提供begin和end找到开头和结尾的迭代器即可通过迭代器本身进行位置控制。使用迭代器解决:迭代器是一个类,其内部通过运算符重载(
2025-06-29 21:44:56
706
原创 二叉树找到下一个中序遍历节点的思路
2.对于cur=parent->right:cur作为一个右子树已经遍历完了,那么就意味着parent这颗子树已经被遍历完了,那就变成的二的情况,将parent当作cur继续重复即可,直到出现情况1或者cur->parent==nullptr结束。那么就会有两种情况:1.cur=parent->left 2.cur=parent->right。1.对于cur=parent->left:cur作为一个左子树已经被遍历完了,所以下一个就是parent。
2025-06-29 20:14:36
229
原创 red-black-tree
由于规则5的限制我们知道红黑树的最短的路径是全黑的,如果这个树n个节点,那么他的最短路径最长不能超过就是log(n),那么他的最长路径最长就不能超过2*log(n)。如果是非空树插入,那么插入的节点就必须是红色的,因为非空树的插入是黑色的话就破坏了黑规则,而黑稿规则是很难维护的。3.非空树的插入,如果他的父亲节点是黑色的,那么没有问题;插入的newnode一定是红色的,一定不能时黑色的,因为黑高是很难维护的。红色节点的两个子节点都必须是黑色的。p为父亲节点,g给父亲节点的父亲节点,u为父亲节点的兄弟节点)
2025-06-28 14:22:40
693
原创 AVL树中的旋转
为了保持搜索二叉树尽量平衡,设计出了AVL树,这种树得到比一般的搜索二叉树多了一个规则:任意节点的左右子树的高度差小于等于1。当我们进行搜索二叉树的插入时难免会出现违背这个规则的子树,那么我们就需要对这个子树进行旋转。不符合规则的子树一共有4种情况。
2025-06-25 18:12:46
397
原创 二叉搜索树
若左子树不为空,那么左子树上的所有节点的值都小于或等于根节点的值;若右子树不为空,那么右子树上的所有节点的值都大于或等于根节点的值。并且他的左右子树也满足上述要求。二叉搜索树又叫做二叉排序树,将二叉搜索树进行中序排列正好是升序的。当然二叉搜索数得到主要功能肯定是用来搜索的。
2025-06-23 13:57:34
396
原创 动态多态:虚函数表(c++)
函数重载:1.两个函数在同一个作用域2.函数名相同但是参数不同,函数的返回值可以相同可以不同函数重写/覆盖:1.两个函数分别在继承体系中的基类和派生类不同作用域2.函数名,参数,返回值都是相同的3.两个函数都是虚函数隐藏:1.两个函数分别在继承体系中的基类和派生类不同作用域2.函数名相同3.函数不构成重写4.不止针对函数,也针对父子类的成员变量注意:隐藏就是隐藏而不是覆盖,也就是说在派生类中仍能找到基类被隐藏的部分。
2025-06-21 16:37:48
917
原创 共享内存
这个函数就是将指定的共享内存挂接到指定的进程的虚拟地址空间中并返回这个虚拟地址;共享内存的大小在创建的时候一定是4KB的整数倍, 内核中的共享内存大小一定是4KB的整数倍,但是你申请的大小是你能使用的大小。⼀旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递 不再涉及到内核,换句话说是进程不再通过执⾏进⼊内核的系统调⽤来传递彼此的数据。key(表示共享内存的唯一性,但是应该注意这个key不是内核形成的,而是在用户层通过函数传共过去的):所以说创建的这个共享内存对应的结构体中一定有这个key值。
2025-03-13 21:37:13
419
原创 命名管道,共享内存
注意:管道总是有一方先想要打开管道文件,但是此时还不能真的打开,而是处于一个阻塞的状态,当两一方也想要打开时,两个进程将会同时打开这个管道文件。读打开会阻塞直到写端打开,反之亦然,除非使用非阻塞模式。所以磁盘中仅仅存放了这么一个文件,但是没有文件的内容。跟匿名管道殊途同归,都是通过文件的缓冲区实现进程之间看到同一份资源。两个进程共享同一份物理内存数据,但逻辑上通过虚拟内存机制保持隔离。首先有一个问题:用两个不相关的进程打开同一个文件,操作系统会进行两次加载吗?不需要,两个进程的用户空间内存(例如通过。
2025-03-11 11:20:30
186
原创 动静态链接与加载
对于多个.o文件在没有链接之前互相是不知到对方存在的,也就是说这个.o文件中调用函数的的跳转地址都会被设定为0(当然这个函数是在其他.o文件中定义的)这个地址会在哪个时候被修正?链接的时候!为了让链接器将来在链接时能够正确定位到这些被修正 的地址,在代码块(.data)中还存在⼀个,这张表将来在链接的时候,就会根据表⾥记录的地址将其修正。这也就是为什么.o文件叫做可重定位文件。所以,链接过程中会涉及到对.o中外部符号进⾏地址重定位。
2025-02-19 17:56:40
1082
1
原创 软硬链接?
硬链接的话,它是直接指向文件的数据块。也就是说,创建一个硬链接时,实际上是创建了一个新的文件名,指向同一个inode。inode是文件系统中用来存储文件元数据的数据结构,比如权限、所有者、文件大小,以及数据块的位置等。所以,当创建硬链接时,两个文件名都指向同一个inode。这样,无论通过哪个文件名访问,都是访问同一个文件内容。而且,只有当所有硬链接都被删除后,文件的数据块才会被释放。软链接则更像是一个快捷方式。它本身是一个单独的文件,里面存储的是目标文件的路径。
2025-02-17 20:00:02
1065
原创 静动态库(xixi)
在一般情况下系统在执行可执行程序的时候会搜索系统共享库路径(/user/lib , /user/local/lib ,/lib64) 和环境变量LD_LIBRARY_PATH的内容中的路径。静态库的使用主要是在编译自己写好的.c文件的时候,要指明库名,库的路径,头文件的路径进行编译,编译完成后运行时就不需要用库了。跟静态库的使用类似在编译.c文件的时候也要指明动态库的路径,动态库的名字,相应头文件的路径。与静态库不同的是,使用动态库在执行可执行程序的时候是需要动态库本身的。静态库:程序在编译链接的时候把。
2025-02-17 19:54:13
502
1
原创 文件系统惹(细)
os文件系统访问磁盘,不是以扇区为单位的,,一般是4KB(也就是连续的8个扇区)(可以调整大小)。磁盘就是⼀个三维数组,我们把它看待成为⼀个"⼀维数组",数组下标就是LBA,每个元素都是扇区每个扇区都有LBA,那么8个扇区⼀个块,每⼀个块的地址我们也能算出来。知道LBA:块号 = LBA/8知道块号:LAB=块号*8 + n. (n是块内第⼏个扇区)文件系统使用磁盘块,是以4KB为单位的。
2025-02-14 21:30:09
980
原创 文件描述符
这里给大家推荐一篇文章存储基础 — 文件描述符 fd 究竟是什么?- 知乎c语言中的文件操作比如fwrite,fread等等的返回值是一个FILE*类型的指针,这个指针指向的是一个结构体,其最终封装了文件描述符。
2025-02-06 20:40:00
950
原创 IO-IO!!
1.侠义理解文件是在从盘上的。磁盘是永久性存储介质。磁盘是外设。磁盘上对文件的所有操作,都是对外设的输入输出IO。2.广义理解linux下一切皆文件(键盘,显示器,网卡,磁盘)3.文件操作的归类认识对于0KB的空文件是占有空间的。文件=文件本身的属性+文件的内容。所有的文件操作都是对文件内容和文件属性的操作4.系统角度对文件操作的本质是进程对文件的操作。磁盘的管理者是操作系统。文件的读写本质上不是通过c/c++语言的库函数来操作的(这些库函数只是用来为用户提供方便的)而是。
2025-02-04 19:28:50
787
3
原创 linux
我们的shell是个进程首先fork创建子进程,父进程只需要wait就好了,子进程转而进行程序的替代,加载新的程序执行,然后我们对应的命令就可以执行了。进程替换:在程序替换的过程中,并没有创建新的进程,只是将当前进程的代码和数据用新的程序的代码和数据覆盖式的进行替换!exec*系列的函数成功替换的时候是没有返回值的,只有替换失败才有返回值,返回值为-1,不用对返回值做判断只要返回就是失败。调用execl的思路就是我要执行谁(也就是要指明路径),我要怎么执行它(也就是说明执行的方式),最后以NULL结尾。
2025-01-23 19:34:34
351
原创 二叉搜索树
二叉搜索树又叫做二叉排序树,他或者是一棵空树,或者具有以下性质;1.若左子树不为空,则左子树上的所有节点都小于等于根节点的值。2.若右子树不为空,则右字数上的所有节点都大于等于根节点的值。3.可以看出二叉搜索树的左右子树也是二叉搜索树。(聪明的的读者已经知道,对一个二叉搜索树做中序遍历是一个升序的序列,但是天才的读者肯定知道这并不是这个树形结构的主要用处,因为他叫搜索树,接着天才的读者已经知道,当你在查找的时候每一次比较都能排除一个(左或者右子树)这他妈效率爽啊,但是我们的根节点是谁呢?
2024-12-13 10:07:46
255
原创 多态性和抽象类
在虚函数后面写上=0;就是一个纯虚函数(什么都不做的函数,不需要定义实现,只要声明就行)。包含纯虚函数的类叫做抽象类,抽象类不能实例出对象。如果派生类继承后没有重写纯虚函数也就还是抽象类。
2024-12-12 20:16:00
354
原创 继承c++
address(address),_num(num),person(name, age)//一定是要调用基类的构造函数来初始化,并且在初始化时,先调用的是person()也就是基类的构造函数,person(s),_num(s._num),_address(s._address)//构造函数也是必须要调用基类的构造函数,//事实上派生类的析构函数不需要手动调用基类的析构函数,在析构完你想要析构的派生类中的成员后会自动调用基类的析构函数。//并且析构函数的调用是先调用派生类的析构函数,在调用基类的析构函数。
2024-12-08 17:07:06
493
原创 模板初阶(c++)
函数模板是代表了一个函数家族,该函数模板与类型无关,在使用的时被参数化,根据实参类型产生对应类型的函数。(注意这是一个新的函数而不是原来的函数模板,函数模板不是函数,函数模板参数化之后才是函数)class 类模板名类内成员的定义;//下面是类模板public:t* _array;//new一个t类型的数组_size = 0;//声明void Stack<t>::pushstack(const t& date)//定义int main()
2024-09-22 09:05:23
623
2
原创 输入输出流(c++)
程序的输入是指从输入文件将数据传送给程序,程序的输出是指从程序将数据传送给输出文件。c++的输入输出包括下面3个方面:1.对系统指定的标准设备输入输出,即从键盘输入,输出到显示屏。也叫标准I/O。2.一外存磁盘(或者光盘)文件进行输入输出。这种以外存文件为对象的输入输出叫做文件的输入输出,简称文件I/O。3.对内存指定空间的输入输出简称文件I/O,通常指定一个字符数组作为存储空间。叫做字符串输入输出,简称串I/O。
2024-09-09 20:06:53
362
原创 继承与派生(c++)
有的时候我们会遇到一个类中包含了很多已经声明过的类中的成员,这个时候就不想再去重新声明。就像是我们声明了一个马的类,我们还想声明一个公马的类,我们希望只加入性别这么一个成员变量,而其他马的性质可以通过继承已经声明过的马的类。一个新类从已有的类中获得自己已有的特性叫做类的继承。从已有的类(父类)产生一个新的子类称为类的派生。可以理解到:派生类是比基类更加具体的,而基类的派生类的抽象。
2024-09-09 08:30:09
940
1
原创 多态性与虚函数(c++)
在c++程序设计中,多态性是指具有不同功能的函数可以是同一个函数名。所以函数重载跟运算符重载都是函数的多态性的体现。其实多态性在生活中也有体现,比如说校长发布说明天要开学了,对于这么同一个消息,学生要补作业,老师要备课,家长要早起做饭...。从系统实现的叫角度来看,多态性分为静态多态性和动态多态性。静态多态性是在程序编译时就能决定调用哪一个的,有被称为编译时的多态性。静态多态性就是通过函数重载实现的。动态多态性是在程序运行过程中才动态地确定操作所针对的对象。又被称为运行时多态性。
2024-09-05 16:10:28
1412
2
原创 函数栈帧的创建和销毁(C)
main函数也是被其他函数调用的,mainCRTStartup函数调用了__tmainCRTStartup函数,而__tmainCRTStartup函数又调用了main函数。在使用参数的时候是找到原来压栈时的空间的值,注意啊,这里的值时放在跟原来不同的空间中的,可以理解为新的变量,是原来变量的临时拷贝,所以改变形参并不能改变实参。每一次调用函数,都会去更低地址的栈区(因为内存的使用是从高地址到低地址使用的)上维护属于这个函数的函数栈帧。函数的参数就先被以压栈的形式传到低地址保存。
2024-08-17 11:03:33
387
6
原创 c语言编译链接
3.开始执行程序代码。编译时,每一个.c文件会独立的编译成一个.obj的目标文件,然后链接器将一个工程中所有的.obj目标文件链接起来形成一个.exe的可执行文件。--处理#include预编译指令,将包含的头文件内容插入到该预编译指令的位置,这个过程是递归进行的,也就是说被包含的头文件也 可能包含其他文件。这里的分析指的是语义的静态分析,通常包括:声明和类型的匹配,类型的转换等。将生成的.i文件输入到扫描器进行简单的词法分析,把代码中的字符分割成一系列的标记(关键字,标识符,字面量,特殊字符等)
2024-08-15 16:41:29
704
5
原创 快排之自省排序(蒟蒻写)
是introspective sort的缩写,introspective的意思是内省的。他的名字就表达了他的思路,思路就是进行自我侦察反省,快排递归太深那就说明在这种数据序列下,选key出现了问题,性能在快速的退化,那么就不要再用快排分割递归了,该换为堆排序进行排序。
2024-08-15 11:29:19
207
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅