- 博客(47)
- 收藏
- 关注
原创 Linux网络:网络编程套接字
因为服务器就是为了给别人提供服务的,因此服务器必须要让别人知道自己的IP地址和端口号,IP地址一般对应的就是域名,而端口号一般没有显示指明过,因此服务端的端口号一定要是一个众所周知的端口号,并且选定后不能轻易改变,否则客户端是无法知道服务端的端口号的,这就是服务端要进行绑定的原因,只有绑定之后这个端口号才真正属于自己,因为一个端口只能被一个进程所绑定,服务器绑定一个端口就是为了独占这个端口。需要注意的是,我们获取到的客户端的端口号此时是网络序列,我们需要调用ntohs函数将其转为主机序列再进行打印输出。
2024-09-28 23:21:36 1080
原创 C++11:线程库
由于thread提供了移动赋值函数,因此当后续需要让该线程对象与线程函数关联时,可以以带参的方式创建一个匿名对象,然后调用移动赋值将该匿名对象关联线程的状态转移给该线程对象。线程函数的参数是以值拷贝的方式拷贝到线程栈空间中的,就算线程函数的参数为引用类型,在线程函数中修改后也不会影响到外部实参,因为其实际引用的是线程栈中的拷贝,而不是外部实参。当线程函数的参数类型为引用类型时,如果要想线程函数形参引用的是外部传入的实参,而不是线程栈空间中的拷贝,那么在传入实参时需要借助ref函数保持对实参的引用。
2024-09-19 20:00:00 1103
原创 C++11:异常与智能指针
实际中很多公司都会自定义自己的异常体系进行规范的异常管理。公司中的项目一般会进行模块划分,让不同的程序员或小组完成不同的模块,如果不对抛异常这件事进行规范,那么负责最外层捕获异常的程序员就非常难受了,因为他需要捕获大家抛出的各种类型的异常对象。因此实际中都会定义一套继承的规范体系,先定义一个最基础的异常类,所有人抛出的异常对象都必须是继承于该异常类的派生类对象,因为异常语法规定可以用基类捕获抛出的派生类对象,因此最外层就只需捕获基类就行了。
2024-09-17 23:45:00 1167
原创 C++11
在2003年C++标准委员会提交了一份技术勘误表(简称TC1),使得C++03这个名字取代了C++98成为C++11之前的最新C++标准名称。但由于C++03主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把这两个标准合并称为C++98/03标准。从C++0x到C++11,C++标准10年磨一剑,第二个真正意义上的标准姗姗来迟。
2024-09-17 18:48:33 1328
原创 【项目】高并发内存池
本项目实现的是一个高并发的内存池,原型是Google的一个开源项目tcmalloc,tcmalloc全称Thread-Caching Malloc,即线程缓存的malloc,实现了高效的多线程内存管理,用于替换系统的内存分配相关函数malloc和free。tcmalloc的知名度也是非常高的,不少公司都在用它,比如Go语言就直接用它做了内存分配器。本项目是将tcmalloc最核心的框架简化后拿出来,模拟实现出一个高并发内存池,目的是为了学习tcamlloc的精华。
2024-09-14 11:09:24 1020
原创 C++:位图/布隆过滤器+海量数据处理
构造一个16位的位图,所有位都初始化为0。构造一个16位的位图,根据所给值初始化位图的前n位。构造一个16位的位图,根据字符串中的0/1序列初始化位图的前n位。
2024-08-31 23:00:00 1186
原创 C++:unordered_map和unordered_set模拟实现
现在由于我们在哈希结点当中存储的数据类型是T,这个T可能就是一个键值,也可能是一个键值对,对于底层的哈希表来说,它并不知道哈希结点当中存储的数据究竟是什么类型,因此需要由上层容器提供一个仿函数,用于获取T类型数据当中的键值。但遗憾的是,我们无法找到一种能实现字符串和整型之间一对一转换的方法,因为在计算机中,整型的大小是有限的,比如用无符号整型能存储的最大数字是4294967295,而众多字符能构成的字符串的种类却是无限的。因为哈希表当中存储的结点都是new出来的,因此在哈希表被析构时必须进行结点的释放。
2024-08-31 17:41:42 1151
原创 Linux:Linux线程池
五个线程在处理时会呈现出一定的顺序性,因为主线程是每秒Push一个任务,五个线程中只会有一个线程获取到该任务,其他线程都会在等待队列中进行等待,当该线程处理完任务后就会因为任务队列为空而排到等待队列的最后,当主线程再次Push一个任务后会唤醒等待队列首部的一个线程,这个线程处理完任务后又会排到等待队列的最后,因此这五个线程在处理任务时会呈现出一定的顺序性(2-3-4-5-1)由于系统调用接口过于复杂,线程模块完成的便是线程的封装,降低接口的调用复杂度,提高代码的阅读性并提高代码的复用性。
2024-08-24 09:51:51 1048
原创 Linux:Linux信号量
当执行流在申请信号量时,可能此时信号量的值为0,也就是说信号量描述的临界资源已经全部被申请了,此时该执行流就应该在该信号量的等待队列当中进行等待,直到有信号量被释放时再被唤醒。多个执行流为了访问临界资源会竞争式的申请信号量,因此信号量是会被多个执行流同时访问的,也就是说信号量本质也是临界资源。但信号量本质就是用于保护临界资源的,我们不可能再用信号量去保护信号量,所以信号量的PV操作必须是原子操作。信号量的初始值为1,说明信号量所描述的临界资源只有一份,此时信号量的作用基本等价于互斥锁。
2024-08-22 19:55:53 975
原创 Linux:生产者消费者模型
生产者和消费者彼此之间不直接通讯,而通过这个容器来通讯,所以生产者生产完数据之后不用等待消费者处理,直接将生产的数据放到这个容器当中,消费者也不用找生产者要数据,而是直接从这个容器里取数据,这个容器就相当于一个缓冲区,平衡了生产者和消费者的处理能力,这个容器实际上就是用来给生产者和消费者解耦的。仍然让生产者生产快,消费者消费慢。运行代码后生产者还是一瞬间将阻塞队列装满后进行等待,但此时不是消费者消费一个数据就唤醒生产者线程,而是当阻塞队列当中的数据小于等于队列容器的一半时,才会唤醒生产者线程进行生产。
2024-08-22 19:23:43 961
原创 Linux:Linux线程安全
因为该执行流第一次申请锁的时候是申请成功的,但第二次申请锁时因为该锁已经被申请过了,于是申请失败导致被挂起直到该锁被释放时才会被唤醒,但是这个锁本来就在自己手上,自己现在处于被挂起的状态根本没有机会释放锁,所以该执行流将永远不会被唤醒,此时该执行流也就处于一种死锁的状态。临界区内的线程完全可能进行线程切换,但即便该线程被切走,其他线程也无法进入临界区进行资源访问,因为此时该线程是拿着锁被切走的,锁没有被释放也就意味着其他线程无法申请到锁,也就无法进入临界区进行资源访问了。由于只有一条指令,保证了原子性。
2024-08-22 17:52:37 811
原创 Linux:Linux多线程
在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”。一切进程至少都有一个执行线程。线程在进程内部运行,本质是在进程地址空间内运行。在Linux系统中,在CPU眼中,看到的PCB都要比传统的进程更轻量化。透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流。
2024-08-22 16:35:58 1314
原创 Linux:Linux进程间通信
对于管道的场景来说,互斥就是两个进程不可以同时对管道进行操作,它们会相互排斥,必须等一个进程操作完毕,另一个才能操作,而同步也是指两个进程不能同时对管道进行操作,但这两个进程必须要按照某种次序来对管道进行操作。消息队列实际上就是在系统当中创建了一个队列,队列中每个成员都是一个数据块,这些数据块都由类型和信息两部分构成,两个互相通信的进程通过某种方式看到同一个消息队列,这两个进程向对方发数据时,都在消息队列的队尾添加数据块,这两个进程获取数据块时,都在消息队列的队头取数据块。
2024-08-05 20:34:06 970
原创 Linux:Linux文件系统
在我们的磁盘上,有大量的文件存储着,这批文件非常的多、杂、乱操作系统对这些文件的管理的部分叫做文件系统在Linux_文件系统(内存)一文中我们了解了文件描述符、重定向、缓冲区等应用级概念,这些都是从内存中看待文件的方式,如果想更全面的了解Linux的文件系统,必须从内存中出来了解物理磁盘是什么样的,存储单元是什么样,操作系统如何看待磁盘从磁盘中一步步走到内存,把知识从想象变为实体。
2024-07-31 20:33:35 957
原创 Linux:Linux文件IO
打开一个文件–>fopen()关闭一个文件–>fclose()对文件进行写入–>fwrite()对文件进行读取–>fread()具体这些函数的使用,可以通过这篇文章回顾一下C语言—文件操作总体看,这套文件操作的使用逻辑就是:打开一个文件,对文件进行操作,关闭这个文件;为了让操作的时候能找到这个文件,C语言提供了一个FILE*的结构体指针,里面存着可以找到文件的成员变量,打开文件的同时返回这样一个指针,之后的对FILE*的操作即使对文件的操作。
2024-07-31 17:26:19 753
原创 Linux:Linux进程控制
为什么要这么多接口呢?适配不同的使用情况事实上,只有execve是真正的系统调用,其他最终都会调用execve,所以只有execve是在man手册的第2页,其它都是第3页。
2024-07-23 17:06:42 1120
原创 Linux:Linux进程概念
在讲解进程之前,我们需要先铺垫一些计算机硬件、操作系统的知识,进而丝滑的理解进程的概念,然后再通过进程切入,从而理解操作系统。1. 冯诺依曼体系结构1.把需要的程序和数据送至计算机中。2.必须具有长期记忆程序、数据、中间结果及最终运算结果的能力。3.能够完成各种算术、逻辑运算和数据传送等数据加工处理的能力。4.能够按照要求将处理结果输出给用户。1.输入数据和程序的输入设备;(键盘、磁盘、网卡、显卡、话筒、摄像头等)2.输出处理结果的输出设备。(显示器、磁盘、网卡、显卡、音响等)
2024-07-21 13:58:07 787
原创 Linux:Linux环境基础开发工具
在Linux下安装软件,一个通常的办法是下载到程序的源代码,并进行编译,得到可执行程序但是这样太麻烦了,于是有些人把一些常用的软件提前编译好,做成软件包(可以理解成windows上的安装程序)放在一个服务器上,通过包管理器可以很方便的获取到这个编译好的软件包,直接进行安软件包和软件包管理器,就好比 “App” 和 “应用商店“”这样的关系yum(Yellow dog Updater,Modified)是Linux下非常常用的一种包管理器,主要应用在Fedora,RedHat,Centos等发行版上。
2024-07-20 16:14:34 951
原创 Linux:Linux权限
根据测试,我们得出以下结论:在Linux中目录的r权限:用户能否查看指定目录内的文件信息目录的w权限:用户能否在指定的目录内新建、修改、删除文件目录的x权限:用户能否进入目录。
2024-07-20 12:48:03 2915
原创 C++:map和set封装
有了以上推论,我们可以对节点定义进行改变//改变红黑节点的定义,使用更高维度的泛型T _data;color _col;//构造函数,_col(RED){}这里使用T来标识数据类型,因为节点可能是K类型的(set传过来的),也可能是pair类型的(map传过来的)
2024-06-06 23:30:00 787
原创 C++:红黑树
/颜色enum colorRED,BLACK//红黑树节点的定义color _col;//构造函数,_kv(kv),_col(RED){}在节点的定义中,为什么要将节点的默认颜色给成红色的?新插入节点的颜色只会影响性质3或者性质4(新插入的节点不是根节点的时候),如果新插入的节点是黑色的节点,那么一定会破坏性质4,破坏性质4要想让红黑树平衡最坏的情况需要将整颗树的节点都动一遍,很难维护。
2024-06-06 22:30:00 732
原创 C++:AVL树
int _bf;//平衡因子//AVL树并没有规定必须要选择设计平衡因子,只是一个实现的选择,方便控制//构造函数:_kv(kv), _bf(0){}
2024-06-06 21:30:00 625
原创 C++:map和set
map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元 素。在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的 内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型 value_type绑定在一起,为其取别名称为pair: typedef pair<const Key, T> value_type;在内部,map中的元素总是按照键值key进行比较排序的。
2024-06-06 16:39:02 673
原创 C++:二叉搜索树
关于数据结构中的树,想必都不会很陌生,今天,主要给大家一起学习搜索二叉树(BST)前面,我们掌握学习过二叉树的三种遍历方式(前序,中序,后序的递归版本),以及我们实现过顺序结构的树(堆),前面的树在储存数据方面,并没有多大的意义,而今天所说的二叉搜索树在数据存储方面就有了很大的意义。
2024-06-06 15:56:51 936
原创 C++:多态
多态的构成条件多态是不同继承关系的类对象,去调用同一函数,产生不同的行为(基类对象和派生类对象去调用同一函数所产生的效果不同)。1.被调用的函数必须是虚函数,且必须完成虚函数的重写。2.必须通过基类的指针或者引用去调用虚函数。public:cout << "抢到五元钱" << endl;cout << "抢到五角钱" << endl;Student s;Print(p);//调用父类的BuyTicketPrint(s);
2024-05-15 16:23:10 543
原创 C++:继承
Person是父类,也称作基类。Student是子类,也称作派生类。子类以public方式继承父类public继承方式下基类中public和protected修饰的成员在子类中的权限没有发生变化基类中private修饰的成员在子类中不能直接被访问(不可见)那么我们在设计类的时候访问权限的设置就可以用如下的考虑方式:成员如果想要在类外被访问,将其设置为public如果成员不想在类外直接被访问,但是要在子类中直接被访问,可以将其设置为protected。
2024-05-15 15:14:55 1015
原创 C++:STL-容器适配器-优先级队列
1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:empty:判空操作back:获取尾部元素操作。
2024-05-09 15:57:18 800 1
原创 C++:STL-vector
vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。
2024-05-09 14:49:34 613 1
原创 C++:STL-string
1.字符串时表示字符序列的类。2.标准的字符串类提供了对此类对象的支持,其接口累死与标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。3.string类是使用char(即作文他的字符类型,使用他的默认char_traits和分配器类型)4.string类是basic_string模版类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作文basic_string分默认参数(根于更多漫步信息参考basic_string)。
2024-05-09 13:39:01 1066 1
原创 C++:模板(初阶)
与函数模板的定义形式类似,类模板也是使用template关键字和尖括号“<>”中的模板形参进行说明,类的定义形式与普通类相同。
2024-04-11 00:15:54 906 1
原创 C/C++内存管理
new的原理1. 调用operator new函数申请空间2. 在申请的空间上执行构造函数,完成对象的构造delete的原理1. 在空间上执行析构函数,完成对象中资源的清理工作2. 调用operator delete函数释放对象的空间new T[N]的原理1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对 象空间的申请2. 在申请的空间上执行N次构造函数delete[]的原理。
2024-04-10 22:17:12 1600 1
原创 C++:类与对象(三)
本来是用2022构造一个临时对象Date(2022),再用这个对象拷贝构造d2,但是C++编译器在连续的一个过程中,多个构造会被优化,合二为一,所以这里被优化为直接构造。在类和对象阶段,一定要体会到,类是对某一类实体(对象)来进行描述的,描述该对象具有那些属性,那些方法,描述完成后就形成了一种新的自定义类型,才用该自定义类型就可以实例化具体的对象。而此刻这个日期类也发生了隐式类型转换,本来整形和日期类没有任何关系,但是我们写的类支持一个单参数的构造函数后,整形就可以构造一个日期类的对象。
2024-04-10 21:35:13 828 1
原创 C++:类与对象(二)
如果一个类中什么成员都没有,简称为空类。空类中什么都没有吗?并不是的,任何一个类在我们不写的情 况下,都会自动生成下面6 个默认成员函数。构造函数是一个特殊的成员函数,名字与类名相同 , 创建类类型对象时由编译器自动调用 ,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次。其特征如下:1. 函数名与类名相同。2. 无返回值。3. 对象实例化时编译器自动调用对应的构造函数。4. 构造函数可以重载。
2024-04-10 20:55:47 678 1
原创 C++:类与对象(一)
class为定义类的关键字,Name为类的名字,{}中为类的主体,注意类定义结束时后面分号。类中的元素称为类的成员,类中的数据称为类的属性或者成员变量,类中的函数称为类的方法或者成员函数。将类的声明和定义全部放在类中定义在头文件中放类的声明,在源文件中放类的定义。
2024-03-27 14:20:30 621
原创 C++:基础篇
C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等。C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计。面向对象程序设计是一种新的程序设计范型。程序设计范型是指设计程序的规范、模型和风格,它是一类程序设计语言的基础。
2024-03-27 13:13:49 739
原创 数据结构—栈和队列
栈是限定仅在表尾进行插入和删除的线性表,又称后进先出的线性表。有顺序栈和链栈。栈的主要操作有进栈和出栈,对于顺序栈的进栈和出栈要注意判断栈满和栈空。队列是一种先进先出的线性表。只允许在一段进行插入,一段进行删除。有循环队列和链队。队列的主要操作就是进队和出队,对于顺序表示的循环队列的进队和出队操作要注意判断队空和队满。队列和栈都不支持随机访问和随机插入。
2024-03-12 10:42:23 796 1
原创 数据结构—顺序表和链表
在程序中,经常需要将一组(通常是同为某个类型的)数据元素作为整体管理和使用,需要创建这种元素组,用变量记录它们,传进传出函数等。一组数据中包含的元素个数可能发生变化(可以增加或删除元素)。对于这种需求,最简单的解决方案便是将这样一组元素看成一个序列,用元素在序列里的位置和顺序,表示实际应用中的某种有意义的信息,或者表示数据之间的某种关系。这样的一组序列元素的组织形式,我们可以将其抽象为 线性表。一个线性表是某类元素的一个集合,还记录着元素之间的一种顺序关系。
2024-03-11 21:31:34 900 1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人