- 博客(35)
- 收藏
- 关注
原创 继承:从 is-a 分界线到菱形继承的独木桥
继承通过抽取公共成员与行为实现代码复用,避免重复。判断是否使用继承应遵循“is-a”原则:若“X是一个Y”成立则用继承,否则用组合(has-a)。C++中默认class为私有继承,易引发访问问题,故继承方式必须显式声明。三种继承方式影响成员访问权限,protected专为派生类设计,private成员虽不可见但被继承并占用内存。构造顺序为先基类后派生类,析构则相反,由语言自动保证。
2026-10-24 17:11:15
105
6
原创 模板进阶:编译期代码生成、三类参数、特化与分离编译
把模板定义连声明一起写进Func.hFunc.cpp// 方案二:定义直接放头文件。包含它的编译单元在编译期自己实例化,// 不需要链接器去别处找地址——这就是模板普遍写在头文件里的原因#endif每个包含这份头文件的编译单元,在用到的地方自己实例化,用什么类型现场生成什么,链接器再把多个编译单元生成的同名实例去重合并。“去重”这件事同样可以实测。两个.cpp各自调用两个目标文件各带一份,符号名完全相同(,名字修饰里编进了模板实参Ii即 int);
2026-10-24 16:38:38
250
12
原创 stack、queue、priority_queue、容器适配器完整梳理
容器适配器通过组合方式,为底层容器(如deque、vector)提供受限访问接口,实现栈(stack)、队列(queue)和优先队列(priority_queue)的语义。其核心是“不改变数据存储,仅封装操作”,通过模板参数灵活指定底层容器与比较策略(仿函数),确保接口安全与功能独立。栈遵循后进先出,队列实现先进先出,优先队列则基于堆结构与自定义比较规则,体现“策略分离”设计思想。
2026-10-24 16:37:37
354
16
原创 list:哨兵节点,const_iterator 和 const iterator的区别与迭代器失效
编号坑现象根因处理1不写拷贝构造两个对象共用一条链,析构时 heap-use-after-free默认拷贝构造逐成员复制,_head指针被抄了一份深拷贝:建自己的哨兵,逐个push_back2析构函数留空节点全泄漏,元素的析构函数一次都没执行只或不写析构,数据节点无人回收clear()后再3用当 const 迭代器const修饰的是迭代器自身,++被禁单独写一个4缺iterator到的转换两个独立类型之间没有转换路径补一个接的构造5const 迭代器后置++写错类型。
2026-10-19 12:31:02
132
4
原创 list:哨兵位、双向链接与迭代器失效
int 版本那 24 字节的构成值得算一遍:数据 4 字节,为了让后面两个指针按 8 字节对齐,编译器补 4 字节空洞,再加两个 8 字节指针,正好 24。第一,节点怎么连成一个整体。它的价值是"没有半成品状态":任何一处忘记赋值的地方,表现出来是空指针崩溃,而不是指向随机地址的野指针——后者调试成本高一个量级。这是链表和 vector 最本质的差别:vector 的插入是搬家,list 的插入是接线。复盘顺序按"对象从生到死"排:先看节点和迭代器,再看构造与哨兵初始化,然后是增删改,最后是析构与赋值。
2026-10-18 15:33:39
543
38
原创 vector:三个指针、容量语义与扩容的真实成本
本文系统解析了vector容器的核心机制:基于三指针模型(_start, _finish, _endofstorage)实现动态内存管理,通过左闭右开区间简化逻辑。关键概念包括:size为逻辑长度、capacity为物理容量,二者通过指针相减获得;扩容时需先申请新内存、拷贝元素、释放旧内存,确保深拷贝与迭代器失效处理;容量只增不减,reserve与resize分工明确。均摊时间复杂度为O(1),但扩容成本为O(n)。理解元素生命周期与指针语义是正确实现的关键。
2026-10-18 15:32:31
332
25
原创 【C++】string类模拟实现
本文实现了一个自定义string类,包含成员变量_str、_size、_capacity及静态常量npos,并封装了默认成员函数(构造、析构、拷贝构造、赋值重载)、成员函数(如c_str、size、reserve、push_back、append、insert、erase、find、substr、clear、swap)和运算符重载(如[]、+=、<<、>>、<、<=、>、>=、==、!=)。通过深拷贝确保内存安全,支持迭代器遍历,具备异常安全与高效扩容机制,完
2026-10-11 17:18:45
416
41
原创 【C++】string 常用函数详解
C++的std::string是标准库提供的字符串类,封装字符序列并自动管理内存,支持构造、赋值、遍历、容量操作及字符串修改等丰富接口。其常用成员函数包括size()、length()、capacity()、empty()、clear()、reserve()、resize()等,用于管理字符串长度与空间。支持operator[]、迭代器(begin/end、rbegin/rend)及范围for遍历,便于元素访问与修改。字符串操作如push_back、append、+=、substr、find、c_str等实
2026-10-05 23:21:18
524
52
原创 【C++】泛型编程详解:函数模板与类模板全梳理
本文系统介绍了C++泛型编程中的函数模板与类模板。函数模板通过template<typename T>定义通用代码,编译器根据实参自动实例化对应类型函数,支持隐式和显式实例化,实现类型无关的代码复用。类模板则允许定义可适配多种类型的类,如栈容器,成员函数需在类外重新声明模板。两者均在编译期完成实例化,效率高,是STL等标准库的核心基础。
2026-09-30 12:11:09
200
10
原创 【C++】动态内存管理完整解析:从内存划分到 new delete 底层原理
本文系统梳理了C/C++内存管理机制,涵盖内存分区(栈、堆、静态区、常量区等)、动态内存管理方式及new/delete与malloc/free的差异。重点解析了new/delete在内置类型和自定义类型上的使用原理,强调其自动调用构造/析构函数的特性;介绍了operatornew/operatordelete底层实现及定位new的应用场景,如内存池优化。最后对比了malloc/free与new/delete在语法、异常处理、类型支持等方面的区别,指出正确配对使用的重要性,避免内存泄漏与野指针问题。
2026-09-29 21:33:13
310
46
原创 【C++】Date类的实现
本文详细介绍了自定义Date类的实现,包含私有成员变量(年、月、日)、构造函数及日期合法性校验。通过重载比较运算符(如>、==等),实现日期大小比较,并利用复用机制减少代码冗余。支持加减天数、前置/后置++/--运算,以及日期相减计算天数差。所有函数均考虑效率与安全性,如使用引用传参、const修饰保证不变性,结合GetMonthDay处理闰年二月,确保日期操作正确可靠。
2026-09-28 18:05:51
522
16
原创 【C++】入门基础语法
命名空间用于隔离标识符,解决命名冲突,支持嵌套与分段定义,编译期生效且不占内存。可通过作用域限定、using声明或using指令访问成员,但避免在头文件中使用using namespace。C++输入输出基于流对象(如cin、cout),自动识别类型,支持链式调用,可重载运算符以处理自定义类型。缺省参数简化调用,需从右向左连续设置,不可与重载混用。函数重载通过参数列表区分,返回值不同不构成重载。引用是变量别名,共用内存,提升效率并支持修改实参,但不能绑定临时对象(除非为const引用)。指针与引用区别在于内
2026-09-27 21:52:38
538
12
原创 【C++】static、友元、内部类、匿名对象与拷贝编译器优化全解析
本文系统阐述C++中const与static成员的初始化机制,强调const成员需在构造函数初始化列表中赋值,而static成员须在类外定义并初始化,且所有对象共享。友元机制允许外部函数或类访问私有成员,但破坏封装性,应谨慎使用。内部类作为外部类的作用域成员,可访问其所有成员,但外部类需通过对象访问内部类。匿名对象生命周期短暂,仅存在于创建语句中,适用于临时操作。最后,编译器优化(如RVO/NRVO)可省略拷贝构造,提升性能,尤其在返回局部对象时效果显著。
2026-09-27 20:46:33
347
19
原创 【C++】万字解析类和对象
main 函数并不会直接去调用 Time 类的析构函数,我们要释放的本质是 Date 对象,编译器会调用 Date 类的析构函数,这里我们没有手写 Date 的析构,编译器就自动生成 Date 的默认析构函数,这个默认析构内部会自动调用成员_t(Time 对象)的析构函数,保证 Date 对象内部所有自定义类型成员都能够正确完成销毁。this 指针是编译器提供的隐藏工具,每一个非静态的成员函数,编译器都会自动增加一个隐藏形参,这个形参就是 this 指针,它保存着调用该成员函数的对象地址。
2026-09-27 18:24:23
547
23
原创 【数据结构】计数排序
计数排序是非比较排序,通过统计元素出现频次实现有序。先确定数组最大最小值以计算范围,创建计数数组并清零,遍历原数组统计各数值次数,再据计数顺序回填。其适合数据范围集中的整数,跨度大则浪费空间。算法时间复杂度线性,但需额外计数数组。
2026-09-02 22:31:38
318
7
原创 【数据结构】冒泡,堆,归并排序
<think>我们只需要根据内容生成摘要,≤150字。内容主要是排序算法介绍,包括冒泡、堆排序、归并排序递归和非递归。摘要应概括这些算法的核心思想和复杂度。避免太多细节。我们写简短:介绍三种排序算法:冒泡排序通过相邻比较交换,最坏O(n²),优化可提前结束;堆排序利用大顶堆,建堆后交换堆顶与末尾并调整,O(nlogn);归并排序采用分治,递归/非递归实现,稳定但需额外空间O(n)。确保字数。</think>本文介绍了三种排序算法:冒泡排序通过相邻元素两两比较交换,优化后可提前终止,最
2026-09-02 22:09:47
669
25
原创 【数据结构】排序(快排,选择,直接插入,希尔)
快速排序是基于分治思想的经典交换排序算法,它选定一个元素作为基准值,通过双指针遍历将数组划分为两部分,使基准左侧元素全部小于等于它、右侧元素全部大于等于它,再递归对划分得到的左右子区间重复上述操作,不断缩小待排序范围,最终得到整体有序的数组,平均时间复杂度为 O (nlogn),最坏情况下可达 O (n²),属于不稳定排序。2).Hoare快排选取区间最左侧下标 keyi 作为基准位置,将left 指针移到基准的下一位开始遍历;在外层循环下,使 right先移动,right 从区间右端向左遍历,当。
2026-08-23 00:11:21
364
14
原创 【数据结构】二叉树入门必刷
本文总结了二叉树常见算法题解法,包括单值二叉树判断、相同树比较、对称二叉树验证、子树查找、前中后序遍历实现及二叉树构建与遍历。各题目均采用递归思路,通过判断节点值和结构一致性解决问题,遍历类题目通过统计节点数动态分配数组存储结果。特别地,二叉树构建题目通过前序字符串递归建树,再中序遍历输出。所有解法均给出详细思路和C语言代码实现,展现了递归在二叉树问题中的典型应用。
2026-08-18 20:51:55
251
13
原创 【数据结构】C语言实现链式二叉树
本文系统介绍了链式二叉树的实现与操作,包括节点创建、遍历算法(先序、中序、后序、层序)、节点统计(总数、叶子节点、左右子节点)、高度计算、层级节点查询、节点查找、完全二叉树判断、二叉树翻转和销毁等16个核心功能。重点阐述了递归思想在二叉树操作中的应用,并展示了队列在层序遍历和完全二叉树判断中的关键作用。所有操作均通过C语言实现,提供了完整的代码示例,为理解和实现链式二叉树数据结构提供了全面参考。
2026-08-18 00:12:02
355
8
原创 【数据结构】堆的应用
建堆有两种方式,一种是从堆顶开始向下建堆,另一种是从堆尾开始向上建堆,好像两种建堆方式除了向上调整和向下调整方式不同之外没什么区别,但我们仔细分析一下,其实这两种建堆方式的时间复杂度差别是很大的。向上调整建堆的话,假设是一个数据一个数据参与堆结构的创建,一开始是一个数据,该数据就是堆顶,然后是第二个数据,这个数据要与堆顶比较(向上调整),如此遍历数据,直到数据全部都在堆结构中。建堆完成以后,就是一个大堆,堆顶数据是堆中数据的最大值,要保留 K 个最好的,堆顶放这 K 个里面最差的,用来当门槛。
2026-08-14 01:00:36
262
7
原创 【数据结构】栈和队列oj
②:如果遍历字符串后,所有左括号均以入栈,右括号也都与栈顶匹配,但是栈中仍有元素剩余,说明还有左括号没有匹配完,先销毁再返回false。①在遍历字符串时,左括号入栈,右括号取栈顶元素匹配,但是如果栈中没有元素(栈为空),没有元素说明不匹配,先销毁栈再返回false。在借用栈的时候,一定要写清楚关于栈的代码,如定义栈的结构,栈的初始化,入栈,出栈,取栈顶元素,判空,销毁。队列的特点是先进先出后进后出,而栈的特点是先今后出后进先出,特点不同,所以用队列实现栈的话需要两个队列。往不为空的队列的队列中插入数据。
2026-08-07 18:12:44
270
8
原创 【数据结构】C语言实现队列
入队的思路与单链表尾插异曲同工,插入前先开辟新节点,判断队列是否为空,即头尾指针是否相等,为空则将新结点"头插"进队列,不为空“尾插”进队列即可。判断队列是否为空队列,如果是,抛出异常终止程序,如果不是,使用一个指针记录下当前队头的下一个结点的位置,释放当前队头结点,然后更新队头指针。求队列长度的思路是:创建一个新指针来储存头节点的位置,遍历队列,直至pcur为空,每次循环size++,最后返回size即可。不过,要对传过来的形参断言,没有地址的队列就是没有创建,没创建就无法初始化。同样要进行断言操作。
2026-08-06 00:46:44
240
4
原创 【数据结构】C语言实现栈
使用完栈想要退出函数时,就应该将之前动态开辟的内存释放掉,还给操作系统,即销毁栈。因为top指向的是栈顶元素的下一个位置,因此top的大小正好是栈的长度,所以求栈长直接对ps断言后可以直接返回top.由于栈只能在栈顶出栈,所以不存在尾删头删任意位置的删除等操作,相比于顺序表代码更加简单。在入栈时,需要和顺序表的尾插头插等插入操作一样先判断一下栈内元素是否已满,如果满了则需要给栈扩容。只能在栈顶入栈和出栈,所以不存在尾插头插任意位置的插入,所以不需要再将增容步骤封装为函数了。栈的特点是后进先出,先进后出。
2026-08-06 00:04:00
335
3
原创 【数据结构】单链表oj
链表节点个数为奇数时,快指针的next指针会走到空。,因为在原链表中5节点的后一个节点是值为val的6,如果没有置空,即使没有将6节点尾插,但是依然是可以通过头节点phead来找到6节点,所以就不算真正移除节点。思路:快慢指针,慢指针一次走一步,快指针一次走两步,快指针走的路程是慢指针的两倍,所以如果链表带环则一定会在环中相遇,否则快指针率先走到链表的末尾。所以,思路是:遍历两个链表,得到两个链表的节点数,算出个数差,长的链表先走个数差步,这样两个链表的长度就相同了,可以进行判断。给定一个链表的头指针。
2026-08-03 01:40:14
516
7
原创 【数据结构】C语言实现单链表
本文摘要:文章详细介绍了单链表的基本概念和实现方法。单链表是线性表的链式存储结构,通过节点指针连接,支持高效插入/删除操作。主要内容包括:单链表的创建、初始化、元素操作(尾插/头插/尾删/头删)、查找、任意位置插入/删除、打印、销毁等核心操作的实现原理和代码示例。特别强调了动态内存管理和指针操作的关键点,如二级指针的使用、边界条件处理等。文章还提供了完整的单链表实现代码,包括头文件定义、功能实现和测试用例,可作为学习单链表数据结构的实用参考资料。
2026-04-24 17:32:02
843
13
原创 【数据结构】C语言实现顺序表
顺序表的概念:顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。数组(Array)一段连续的内存空间,用来存储相同类型的数据。只负责存放数据,不自带长度管理、插入、删除、扩容等操作。大小在定义时基本固定(静态数组),越界直接出错。顺序表(Sequential List)逻辑上相邻,物理上也相邻的线性表。绝大多数语言实现的顺序表底层就是数组,并且额外封装了:当前元素个数、最大容量、插入、删除、查找、扩容等完整操作。顺序表分为静态顺序表和动态顺序表。
2026-04-19 22:41:19
802
18
原创 【数据结构】时间复杂度
定义:在计算机科学中,算法的时间复杂度是一个函数式T(N),它定量描述了该算法的运行时间。时间复杂度是衡量程序的时间效率,那么为什么不去计算程序的运行时间呢?1. 因为程序运行时间和编译环境和运行机器的配置都有关系,比如同⼀个算法程序,用一个老编译器进行编译和新编译器编译,在同样机器下运行时间不同。2. 同⼀个算法程序,用⼀个老低配置机器和新高配置机器,运行时间也不同。3. 并且时间只能程序写好后测试,不能写程序前通过理论思想计算评估。那么算法的时间复杂度是⼀个函数式T(N)到底是什么呢?
2026-04-18 21:15:52
826
6
原创 【C语言】动态内存经典笔试题分析
请问运行Test函数有什么样的后果?程序崩溃。对NULL使用了解引用操作对于传值调用和传值调用我们要知道:并不是传个地址,传个指针就是传址调用了,传个指针变量,还是传变量本身,没有传变量的地址就不是传址调用。所以什么时候要用传址调用?需要通过函数改变变量本身时使用传址调用。那么,如何修改这段代码?
2026-04-14 21:33:36
373
8
原创 【c语言】动态内存管理:malloc,calloc,realloc,柔性数组
/在栈空间上开辟四个字节//在栈空间上开辟10个字节的连续空间但是上述的开辟空间的方式有两个特点:• 空间开辟大小是固定的。• 数组在申明的时候,必须指定数组的长度,数组空间一旦确定了大小不能调整但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。C语言引入了动态内存开辟,让程序员自己可以申请和释放空间,就比较灵活了。malloc功能:向内存的堆区申请一块连续可用的空间,并返回指向这块空间的起始地址。参数。
2026-04-14 17:12:05
982
15
原创 C语言自定义类型:结构体,联合体,枚举
本文介绍了C语言中结构体的相关知识,主要包括: 结构体类型的声明和使用方法,包括成员访问和初始化; 匿名结构体的特殊声明方式及其局限性; 结构体自引用的正确实现方式; 结构体内存对齐规则及计算示例,分析了内存对齐的原因和空间优化方法; 如何修改默认对齐数; 结构体传参的两种方式(传值和传址),并推荐使用传址方式以提高效率。
2026-04-12 16:33:52
861
7
原创 C:数据在内存中的存储
其实超过⼀个字节的数据在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分为大端字节序存储和小端字节序存储,下面是具体的概念:大端(存储)模式:是指数据的低位字节内容保存在内存的⾼地址处,而数据的高位字节内容,保存在内存的低地址处。小端(存储)模式:是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容,保存在内存的高地址处。
2026-04-11 22:48:07
584
5
原创 90%的人都弄错的指针题:sizeof和strlen的底层真相
学习c/c++绕不开指针,而指针题里,sizeof和strlen绝对是高频坑点——同样是求长度,结果却是天差地别,数组,指针,字符串混用更是让人头大。很多人刷了无数题,还是挺搞不清二者的本质区别,一遇到就错误,这篇博客从底层逻辑出发,拆解strlen和sizeof的核心差异,让你指针的核心考点。
2026-04-09 13:25:52
724
8
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅