- 博客(45)
- 收藏
- 关注
原创 C++IO流讲解
本文详细介绍了C/C++中的IO流系统。首先讲解C语言的基本输入输出函数scanf和printf的使用方法,包括格式控制、宽度设置等技巧,并深入分析了缓冲区的概念及其作用。其次,文章阐述了C++面向对象的IO流体系,包括标准输入输出流对象(cin/cout)、文件流和字符串流的类关系图。重点探讨了流状态管理机制,通过示例代码展示了good()、eof()、fail()和bad()等状态检测方法的应用场景。最后,详细说明了全局流对象cin和cout的用法,包括基本的输入输出操作和错误处理技术。全文系统性地比较
2025-11-16 18:45:11
1266
原创 C/C++类型转换
本文系统介绍了C/C++中的类型转换机制。首先分析了C语言中的隐式和显式类型转换,指出其存在转换可视性差的缺陷。随后详细探讨了C++中的类型转换扩展,包括内置类型与自定义类型之间的相互转换,重点讲解了通过构造函数和operator关键字实现自定义转换的方法。最后介绍了C++新增的四种类型转换操作符:static_cast用于相关类型转换、reinterpret_cast用于无关类型转换、const_cast用于去除const属性、dynamic_cast用于多态类型转换。文章通过代码示例直观展示了各类转换的
2025-11-15 21:00:32
766
原创 C++特殊类的设计
设计模式是软件工程中一套被反复验证、广泛认可的代码设计经验总结,如同建筑领域的蓝图一样,它们针对特定场景提供了可重用的解决方案。设计模式不仅提升了代码的可重用性、可读性和可维护性,还促进了开发团队之间的高效协作,使软件设计更加标准化和工程化。通过使用这些模式,开发者能够避免重复造轮子,降低系统复杂度,提高软件质量,是构建健壮、灵活软件系统的重要工具。我们之前已经使用过设计模式来编程,适配器模式,迭代器模式等。单例模式也是一种很常见的设计模式,其目的为。
2025-11-14 23:38:17
1078
原创 C++智能指针
本文分析了传统C++手动内存管理的问题,重点探讨了智能指针的必要性和实现原理。主要观点包括:1)手动内存管理容易引发内存泄漏,特别是面对异常时;2)内存泄漏会导致程序性能下降甚至崩溃;3)RAII(资源获取即初始化)思想是解决内存管理的有效方法,通过对象生命周期自动管理资源;4)C++提供了auto_ptr、unique_ptr等智能指针实现,其中auto_ptr采用所有权转移但存在缺陷,unique_ptr通过防拷贝实现独占式管理。智能指针通过重载运算符模拟指针行为,同时确保资源自动释放,是C++内存管理
2025-11-13 23:57:03
1287
原创 Linux多线程之自旋锁与读写锁
摘要:本文详细介绍了Linux中的自旋锁和读写锁两种线程同步机制。自旋锁适用于临界区执行时间短的场景,通过轮询检测避免线程切换开销,但会占用CPU资源。读写锁则针对读者-写者模型设计,允许多个读者并发访问,写者独占访问,提供了更高的并发性能。文章分析了两种锁的工作原理、优缺点、适用场景,并给出了详细的API接口和使用示例,帮助开发者在多线程编程中选择合适的同步机制实现线程安全。
2025-11-12 11:51:34
949
原创 C++异常介绍
实际开发中,许多公司会自定义异常体系进行规范化的异常管理。如果项目中随意抛出异常,外层调用者将难以处理。因此通常会定义一套继承的规范体系,这样所有抛出的都是继承自基类的派生类对象,捕获一个基类即可处理所有异常public:protected:int _id;return str;
2025-11-11 00:24:33
689
原创 Linux网络初始及网络通信基本原理
本文概述了计算机网络的基本概念和分层模型。从网络发展历程引入,阐述了协议的实质(结构化数据格式)和分层设计的优势(模块化、封装性)。重点对比了OSI七层模型(理论标准)和TCP/IP五层模型(实际应用)的分层架构,包括各层核心功能、数据单元和典型协议。此外,介绍了IP地址和MAC地址的作用,以及网络数据传输的封装/解封装流程。文章强调TCP/IP模型因更实用而被广泛采用,同时解释了网络协议栈的"栈"特性源于数据封装时的首部添加机制。
2025-11-07 21:10:16
994
2
原创 C++11新特性介绍
本文介绍了C++11标准的主要改进和新特性。主要内容包括: 统一的列表初始化(initializer_list机制) 声明方式改进(auto/decltype/nullptr) 范围for循环(基于迭代器的自动遍历) STL新容器(array/forward_list/unordered容器) 右值引用与移动语义(左值/右值区分,移动构造/赋值) C++11通过约140个新特性和600个缺陷修正,使语法更加简化、类型系统更安全、开发效率更高,特别在系统开发和库开发方面有显著提升。新特性如列表初始化、自动类型
2025-11-02 19:11:26
636
原创 Linux多线程之生产消费模型,日志版线程池
生产者消费者模型通过共享容器实现解耦,生产者向容器存放数据,消费者从中读取数据。该模型包含三个关键要素:共享缓冲区(交易场所)、生产者和消费者两种角色,以及生产/消费线程间的互斥与同步关系。使用阻塞队列实现时,需通过互斥锁保证线程安全,条件变量实现同步(满时阻塞生产者,空时阻塞消费者)。为防止伪唤醒,需使用while循环而非if判断队列状态。实际应用中可根据任务耗时情况调整生产者和消费者线程数量(如生产快消费慢时采用单生产多消费),通过并发处理耗时任务提高整体效率。代码实现展示了基于pthread的阻塞队列
2025-10-30 20:57:25
1284
原创 Linux多线程控制(创建,等待,分离,终止)
如果线程在执行的时候出现异常,整个进程都会收到操作系统的信号,进而崩掉,所有线程都会退出,他的退出码就是整个进程的退出码,所以说,线程根本没有返回给主线程退出码的机会。
2025-10-30 17:56:55
1050
原创 Linux线程互斥与同步
本文介绍了线程互斥与同步的核心概念。线程互斥通过互斥锁保护临界资源,解决数据竞争问题,确保同一时间只有一个线程访问共享数据。互斥锁的实现依赖于硬件原子指令,如swap/exchange。文章还讨论了死锁的产生条件和避免方法,并提出了RAII风格的锁封装方案。线程同步则用于解决资源竞争导致的饥饿问题,通过协调线程执行顺序提高系统效率。文中结合厨房做饭的比喻,生动解释了互斥锁的工作原理及重要性。
2025-10-27 20:29:25
574
原创 C++STL之unordered_map,unordered_set与哈希表
C++11引入的unordered系列容器基于哈希表实现,相比红黑树实现的map/set,查询效率从O(logN)提升至平均O(1)。文章首先介绍哈希概念,通过数组下标映射实现快速查找,并分析哈希冲突问题及两种解决方案:闭散列(开放地址法)和开散列(链地址法/哈希桶)。重点阐述哈希桶结构,通过vector存储链表节点指针实现冲突处理,并详细说明扩容机制(荷载因子控制)和关键仿函数设计(HashFunc将不同类型转为整型,KOfT提取键值)。最后简要提及哈希表的模拟实现框架,包括节点结构、模板参数设计等核心内
2025-10-20 18:56:01
990
原创 C++STL之map与set模拟实现
map和set底层均采用红黑树实现,其中map存储键值对pair<key,value>,set仅存储key。通过模板参数设计统一接口,map使用RBTree<key, pair<const key,value>>适配,set使用RBTree<key, const key>适配。迭代器实现核心在于中序遍历逻辑:右子树存在时找最左节点,否则寻找第一个右祖先节点。end()迭代器处理采用nullptr简化设计,但需注意根节点变化导致的失效问题。红黑树通过封装和改造同
2025-10-18 17:12:25
468
原创 C++STL反向迭代器设计
反向迭代器摘要 反向迭代器是C++中一种特殊的迭代器适配器,它通过反转普通迭代器的操作逻辑实现反向遍历。主要特点包括:1) 递增操作实际向容器起始方向移动;2) 通过rbegin()/rend()获取迭代器,其中rbegin()指向最后一个元素;3) 解引用时返回基础迭代器前一个位置的元素引用。反向迭代器采用适配器模式封装普通迭代器,支持与普通迭代器相似的操作,但需注意解引用时的特殊处理逻辑。示例代码展示了如何实现反向迭代器类模板及其在链表容器中的应用。
2025-10-18 17:09:55
400
原创 C++二叉搜索树,AVL树与红黑树
二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查 找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii 和E.M.Landis在1962年 发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右 子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均 搜索长度。它的左右子树都是AVL树左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)
2025-10-16 20:29:34
824
原创 C++STL之map与set使用详解
C++ STL中的map与set是关联式容器,它们通过键值对存储数据,检索效率高。map存储键值对,set只存储键且唯一。两者底层采用红黑树实现,元素自动排序。set特性包括元素不可修改、严格排序、去重功能,查找时间复杂度为O(log₂n)。基本操作包括插入、删除、查找等。map还支持键值对操作,而set主要用于去重和排序。两者都支持迭代器遍历,默认按升序排列,也可自定义比较函数。这些容器适用于需要高效查找和排序的场景。
2025-10-09 17:49:07
886
原创 C++多态特性详解
C++多态特性详解 本文详细介绍了C++中的多态特性及其实现原理。多态是指不同对象执行同一操作产生不同结果的能力。实现多态需要满足两个条件:基类和派生类完成虚函数重写,以及通过基类指针或引用调用虚函数。文章分析了虚函数重写的三种特殊情况:协变(返回值类型不同)、析构函数重写和派生类省略virtual关键字。同时介绍了C++11新增的override和final关键字用于检查重写关系。最后探讨了多态的底层实现机制,包括虚函数表的结构和存储位置。通过代码示例展示了虚函数表指针的获取方法,验证了虚表通常存储在静态
2025-10-05 17:18:30
1264
原创 C++封装和继承特性
继承是面向对象程序设计中最核心的代码复用机制。它允许我们在不修改原有类的基础上,通过扩展来创建新的类(称为派生类),从而形成类的层次结构。之前我们可能使用到的复用有函数复用,模板复用,而继承就是第三种复用,是类在设计层次上的复用例如:Person 类作为基类,Student 和 Teacher 类作为派生类,复用 Person 中的成员变量和函数。
2025-10-02 15:54:26
813
原创 C++模板深入理解
我们在使用模板编程的时候,有时候会遇到特殊情况,我们所写的模板可能无法满足我们需要使用的类型的一些要求,无法实现相应功能,因此需要重写一个模板来实现相应功能。// 灾难!比较的是指针地址而非对象内容//这是我们所期待的方式此时,该函数无法实现比较大小的功能,他只会按照指针去比大小,而不是解引用取到值去比较大小,无法实现相应功能,**模板的通用性在这里变成了"错误的通用"——它对所有类型都一视同仁,但指针类型需要特殊处理。**因此需要重写一个模板来实现相应功能。
2025-10-01 01:02:29
892
原创 C++STL之stack,queue与容器适配器
什么是容器适配器?适配器是一种设计模式,它就像一个转换头,能将一个类的接口转换成用户所希望的另一种接口。STL中的stack、queue和priority_queue都是容器适配器,它们没有自己独立的数据结构,而是“适配”了其他容器(如deque, vector)的接口,提供了新的、特定的行为。容器适配器通过封装和限制接口,将通用的顺序容器转化为具有特定语义的专用数据结构。首先在代码清晰度方面,使用 stack 比直接用 vector 并约定只能操作尾部更能明确表达程序员的意图;
2025-09-29 21:57:13
934
原创 C++STL之list
是 C++ STL 中的双向链表容器,底层实现为。支持快速插入和删除(O(1)时间复杂度),不支持随机访问(不能使用下标操作),插入和删除操作不会使迭代器失效(除了被删除元素的迭代器)与 vector 和 deque 相比,list 在任意位置的插入删除性能更优,但随机访问性能较差。
2025-09-28 23:49:33
1025
原创 C++STL之vector
当数组需要增长时,它不是仅仅申请所需的最小空间,而是会一次性申请一块更大的内存(例如,每次扩容为当前容量的 1.5 或 2 倍)。这样,在接下来插入多个元素时,只要数量不超过预分配的空间,就无需再次触发昂贵的扩容过程。我们在扩容的时候,会重新开辟空间,释放旧的空间,若在此前使用了迭代器,则扩容之后迭代器所指的空间还是旧空间中的一个地址,因此成为野指针。扩容时的代价较高,需要申请空间,拷贝数据,释放旧内存空间,因此我们应尽量减少扩容的次数。:只复制指针地址,不复制指针指向的数据,导致多个对象共享同一块内存。
2025-09-27 20:42:36
1177
原创 Linux多线程初识
*线程(Thread)**是进程内部的独立执行流,是CPU调度的基本单位。关键特性每个进程至少包含一个线程(主线程)线程在进程地址空间内运行,共享进程资源在Linux中,线程表现为轻量级的进程控制块(PCB)透过进程虚拟地址空间,可以看到进程的大部分资源,讲进程资源合理分配给每个执行流,就形成了线程执行流。
2025-09-23 00:27:39
928
原创 Linux信号机制详解
信号捕捉SIG_IGN:忽略信号SIG_DFL:恢复默认行为sigaction系统调用其中sa_mask是信号屏蔽字,用于指定在处理当前信号时需要阻塞的其他信号。当一个信号正在被处理时,系统会自动阻塞该信号本身以防止递归调用,但不会自动阻塞其他信号。通过设置sa_mask,可以在处理某个信号时同时阻塞其他指定信号。需要注意的是,某些关键信号(如SIGKILL、SIGSTOP等)是不允许被阻塞的。
2025-09-21 23:57:49
1097
原创 Linux进程间通信
进程间通信(IPC)技术详解 本文系统介绍了Linux系统中的进程间通信机制,重点分析了System V IPC标准中的两种核心方式: 消息队列:通过操作系统维护的队列传递结构化数据块,支持基于类型的选择性接收,适用于异步通信场景。 共享内存:通过物理内存映射实现最高效的数据共享,但需要配合同步机制(如管道)使用以避免竞态条件。文中提供了完整的共享内存封装类实现,包含创建、挂载、初始化和清理等关键操作,并强调共享内存的生命周期独立于进程。 文章还探讨了进程通信的基本原理,指出由于进程隔离特性,必须通过操作系
2025-09-20 00:43:39
1181
原创 Linux软硬链接与动静态库
本文系统介绍了Linux中的软硬链接和动静态库。软链接是包含目标路径的独立文件,硬链接则是共享inode的多文件名引用。静态库在编译时链接到程序,使可执行文件独立但体积大;动态库在运行时加载,节省空间但需环境支持。文章详细对比了它们的特性、创建方法及使用场景,并解释了动态库的加载原理。这些知识对Linux系统管理和程序开发至关重要。
2025-09-17 14:12:43
1098
原创 Linux进程控制核心:创建·等待·终止·替换
/ 返回值:// >0: 父进程,返回值为子进程PID// =0: 子进程// <0: 创建失败为了让父进程方便对子进程进行标识,进而进行管理,所以给父进程子进程的pid,给子进程返回0只是为了确认是否创建成功,出错返回-1//等待最近一个子进程退出//等待pid为pid进程的退出,若pid参数值为-1,则等待任意一个子进程,与wait等效//这两个函数返回值正常返回时为收集到的子进程id,如果调用出错则返回-1调用这两个其中某一个函数时,父进程会进入阻塞等待状态,等待子进程状态发生改变。
2025-08-02 20:44:42
828
原创 Linux文件系统理解2
inode中的datablocks表中,前12个直接寻址(存放的块号,类似于一级指针直接寻找),剩余3个中的前两个间接寻址(存放的块号,该块号对应的块内存放的不是数据,而是更多的块号,第二次找到的块号内存放的是数据,类似于2级指针),最后一个块号是2次的间接寻址(类似于3级指针)我们在找到一个文件时,首先要得到该文件的inode number,该编号是以分区为单位分配的,不是以分组为单位分配,一个分区内的所有inode number都不能重复,是唯一的,inode number不能夸分区访问。
2025-08-02 00:06:35
784
原创 Linux文件系统理解1
本文系统介绍了Linux系统下的文件操作机制。从系统调用层面详细讲解了open/close/read/write等文件操作函数的使用方法,包括文件描述符、权限掩码等关键概念。在操作系统层面,阐述了内核如何通过"先描述后组织"的方式管理文件,包括struct file数据结构、文件描述符表等核心机制。同时揭示了C语言文件操作函数是对系统调用的封装这一本质。最后说明了Linux"一切皆文件"的设计哲学,以及硬件设备如何通过类似文件的方式被管理。全文深入浅出地剖析了Linu
2025-07-22 23:29:40
919
2
原创 Git使用与管理
对象库(objects),修改的工作区内容会写入对象库的一个新的git对象中,达到维护版本的目的,每次add都会有一个commit id,HEAD可以记录最近一次提交的commit id,HEAD^表示HEAD的上次提交的commit id,HEAD^^为上上次,以此类推。master主分支上一般提交稳定的经过测试的代码,但是如果出现bug,则需要新开一个分支去处理,既不能影响我们原先正在开发的分支,也不能影响master分支,因此可以先将我们开发代码的分支上的代码进行保存,在去新建分支处理bug。
2025-07-18 23:38:14
1305
原创 Linux 进程管理核心机制
bash进程启动时,默认会生成两张表。1.argv[],命令行参数表。这张表从命令行获取,即用户输入2.env[], 环境变量表。这张表从os的配置文件获得这两张表bash通过各种方式交给子进程。
2025-07-11 18:48:38
833
原创 Linux进程初识
进程:程序执行的一个实例,包括代码、数据和执行上下文PCB(进程控制块):操作系统管理进程的核心数据结构(Linux中为设计原理:“先描述后组织” - 通过结构体描述进程,再通过数据结构组织管理// Linux中的进程控制块// 包含进程所有管理信息long state;// 进程状态pid_t pid;// 进程ID// 打开的文件信息// ... 其他重要字段。
2025-05-29 22:34:25
864
原创 C++内存管理
若类有显式析构函数,new[]会多分配4字节(32位系统)存储对象数量(位于数组头部)。delete[]根据此数量调用对应次数的析构函数,再释放内存。
2025-05-26 21:01:44
1153
原创 C++类和对象
类似于结构体定义,与C语言不同的是,除了定义成员变量之外,还可以定义成员函数,同时引入访问限定符,来对类的成员进行封装一般在类内定义的成员函数,编译器可能会当成内联函数来处理,因此可以进行声明和定义分离在声明的头文件中如下声明在源文件中如下定义。
2025-04-29 22:24:54
990
原创 C语言文件操作
filename :文件名,即我们要进行打开的文件名mode: 打开文件方式,常用的有以下方式“r”, 只读,为了往程序里输入(读取)数据,打开一个已经存在的文件,如果该文件不存在,则会出错。“w”,只写,为了往文件里输出数据(写入文件),打开一个文本文件,如果指定文件不存在,则会自动创建一个文件,以filename命名。“a”,向文件末尾增加数据,如果指定文件不存在,则会自动创建一个文件,以filename命名。“rb”,与“r”的区别是该方式打开的文件是二进制文件,其余都相同。
2024-09-28 19:46:24
961
1
原创 C语言数据类型及存储
自定义类型是描述复杂的含义,用单一的内置类型无法描述时,所使用的类型,是由用户自己来定义的,通俗一点说就是DIY。告诉编译器我有这个变量,而他的值未知,这是声明。声明后给变量赋值,系统会为变量开辟空间来存储数据,这是定义。也就是说,声明和定义的区别就是有没有分配内存。变量的声明和定义方法如下int age;// 数据类型 变量名称;这一步是声明age = 0;//分配内存空间,存储数据,这一步是定义//声明的时候给他初始化,分配内存空间了,是定义。
2024-09-26 20:12:33
989
1
原创 LCR 171. 训练计划 V
某教练同时带教两位学员,分别以链表l1l2记录了两套核心肌群训练计划,节点值为训练项目编号。两套计划仅有前半部分热身项目不同,后续正式训练项目相同。请设计一个程序找出并返回第一个正式训练项目编号。如果两个链表不存在相交节点,返回null。如下面的两个链表在节点c1开始相交。- 相交的起始节点的值。如果不存在相交节点,这一值为 0l1- 第一个训练计划链表l2- 第二个训练计划链表skip1- 在l1中(从头节点开始)跳到交叉节点的节点数skip2- 在l2中(从头节点开始)跳到交叉节点的节点数。
2024-03-31 21:42:31
1785
2
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅