- 博客(27)
- 收藏
- 关注
原创 C++的单例模式
为了只实例化出一个对象,会将默认构造函数私有,将拷贝构造函删除,由于实例出是的同一个对象,当这个对象被多个线程使用(线程安全问题)或多个模板类使用(重复调用析构函数),需要将析构函数私有,并需要锁进行安全保护,我们需要在public下写能够调用默认构造函数(只调用一次)和析构函数的两个自定义函数。2.更重要的原因:单例模式的对象是自引用,就是我包含我自己,我自己就是我的成员,发生delete时,如果成员有自定义类型,要调用成员的析构函数,而单例对象的成员就是自己,导致无线死循环。分为懒汉模式和饿汉模式。
2025-06-24 15:02:43
499
原创 C++智能指针
可见,并没有成功释放空间,sp1等待着sp2的_prev释放,sp1走了,同时带走了sp1的_next,也就是sp2的一个_pcount,但sp2的_pcount没有减减,导致sp2走了,也没有释放空间。有了计数就要考虑线程安全问题,因为什么时候析构依赖于*_pcount,当线程冲突导致*_pcount少于实际存在的智能指针的数量时,导致重复释放空间。共享指针,一块资源可以有多个智能指针管理,但为了只允许释放一次(最后一个智能指针释放),添加了计数器,当减减之后为计数为0就释放。
2025-06-24 09:55:04
466
原创 C++异常
3. 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。C++异常概念 异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。catch: 在想要处理问题的地方,通过异常处理程序捕获异常.catch 关键字用于捕获异常,可以有多个catch进行捕获。1.异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。
2025-06-23 20:07:42
327
原创 C++11的内容
步骤 1:优先匹配std::initializer_list 构造函数 如果类型 F定义了 接受 std::initializer_list的构造函数 (如 F(std::initializer_list<U>)),编译器会优先尝试调用它。此时,花括号内的所有参数会被打包成一个 std::initializer_list<T>临时对象,其中 T 是花括号内元素的统一类型(需支持隐式转换)。
2025-06-23 19:28:47
1276
原创 C++位图
比如,存在或不存在,通过0或1也可以用多个位图记录多种状态,如 01,10,00,11(在两个位图下,可以记录4种状态,当然也可以横向记录,比如将某个位图的4个位记录状态,这样可以最多记录16种状态)通过不同的方式将(拿string举例)string映射到多个位置(多个位置的位设为1),布隆过滤器不支持删改,当某个位被多个值映射了,删除会影响其他值的检查。将位改为计数器,vector<unsigned char> vc,当映射到了vc[index],v[index]++ (v[index<255)。
2025-06-19 22:39:09
307
原创 C++哈希
在之前使用计数排序的时候,是通过对应的下标对该数组下标对应的空间进行标记,但是如果数分布不均匀就会造成浪费空间(比如1,2,3,999)。于是,哈希就来解决这问题。
2025-06-19 17:05:31
437
原创 用红黑树实现map和set
通过一个_kv就完成了赋值,对于map类型,KV就是pair<K,V>,key就是_kv的first,value就是_kv的second。迭代器是由一个红黑树节点和一些成员函数构成,迭代器的目的就是遍历,获取数据,而获取的数据都是KV类型的,因为_node的成员变量就是kv。map是一种KV模型,在传参时,需要用pair将两个参数耦合,创建了一个类型,而set只需要传一个key值,所有需要统一接口。用结构体创建一个新的类型,再将该类型作为模板传到RBTree类中实例化,调用函数获取键值。
2025-06-16 20:50:08
10
原创 C++红黑树
先定义插入节点(cur)的父节点定义为p(parent),p的父节点定义为g (grandpa) ,g的另外一个孩子定义为u(uncle)。在调节的过程中,cur可能在p的左边,也可能在p的右边,p可能在g的左边,p也可能在g的右边,这些情况交替出现,需要我们用if调节去判断。4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点。当我们向上调节,会出现这种情况(这里只讲p在g的左边的情况)在这里,只讨论p在g的左边情况,p在g的右边同样的思路。cur也可以在p的右边。
2025-06-15 20:35:43
184
原创 AVL树的实现
AVL树是一种自平衡二叉搜索树,通过平衡因子(右子树高度减左子树高度)保证每个节点的左右子树高度差不超过1。本文详细介绍了AVL树的插入操作及四种旋转调节方法(左单旋、右单旋、左右双旋、右左双旋),并提供了代码实现和测试验证。关键点在于:插入节点后需要向上调整祖先节点的平衡因子;当平衡因子变为±2时进行相应旋转;旋转后需要调整相关节点的平衡因子。测试结果表明该方法能正确构建平衡树。
2025-06-14 21:21:53
592
原创 二叉搜索树
二叉搜索树又称二叉排序树,它或者是一棵空树或者是具有以下性质的二叉树:1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。2.若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。3.它的左右子树也分别为二叉搜索树。
2025-06-12 18:58:10
417
原创 virtual继承与虚函数
摘要: 本文系统解析了C++虚函数机制中的关键数据结构。虚函数表(vtable)是存储虚函数指针的数组,实现多态时派生类会覆盖基类对应函数地址。虚基类偏移表(vbtable)用于解决虚拟继承问题,记录了this指针和成员偏移量。文章详细分析了不同继承场景下的内存布局:单继承中派生类虚函数可扩展基类虚表;多继承按声明顺序合并多个虚表;钻石型虚拟继承会创建独立的派生类虚表并保留基类虚表。通过内存模型图解,揭示了虚函数覆盖、虚基类指针等核心机制的工作原理。
2025-06-10 16:34:04
724
原创 C++中的多态
摘要:本文探讨了C++中的多态实现机制,重点分析了虚函数重写条件和特性。多态需要满足两个条件:通过基类指针/引用调用虚函数,且派生类必须重写该虚函数。文章详细介绍了虚函数重写的规范写法,指出协变和析构函数重写两种特殊情况。同时讲解了C++11的final和override关键字用法,以及抽象类和纯虚函数的概念。通过多个代码示例展示了多态的具体应用场景,包括指针/引用调用时的多态表现,以及传值调用时失去多态性的情况。
2025-06-10 10:30:56
422
原创 C++中的继承基础
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。(被继承的类称为基类)继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。通过直接在类后面继承,可以在stu和tea实例化的对象中看到person的成员(已经成为stu和tea的成员了)
2025-06-10 09:44:34
1029
原创 C++中的模板
2. 模板实例化阶段:当代码中实际使用模板(如 std::vector<int>)时,编译器才会根据模板生成具体的类或函数代码(即实例化)。声明文件(.h):仅包含模板的声明,编译器在编译其他源文件(.cpp)时无法看到定义,导致实例化失败。4. 函数形参表: 必须要和模板函数的基础参数类型完全相同(可以大于一个,但要与形参类型的个数匹配)定义文件(.cpp):虽然定义了模板,但其他源文件无法访问它(除非显式实例化),导致链接错误。作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
2025-06-09 15:47:26
328
原创 实现最小栈和优先队列
本文介绍了三种常见数据结构的模板实现:栈、最小栈和优先队列。基础栈通过模板类实现,利用容器适配器(list或vector)的push_back和pop_back操作。最小栈在此基础上增加一个辅助栈来实时跟踪最小值。优先队列采用堆结构实现,包含向上调整和向下调整算法来维护最大堆性质。每种结构都提供了完整的接口实现和测试用例,展示了它们的基本功能和操作流程。这些实现充分体现了C++模板和容器适配器的灵活性,为不同应用场景提供了高效的数据结构解决方案。
2025-06-05 21:43:01
332
原创 数据结构堆
本文介绍了堆排序的基本原理和实现方法。主要内容包括:1)通过数组下标表示完全二叉树,父节点与子节点的下标关系;2)大小堆的定义及特点,小堆根节点最小,大堆根节点最大;3)建堆过程,从最后一个非叶子节点开始调整;4)堆排序算法,升序用大堆,降序用小堆,每次交换堆顶元素后调整剩余堆;5)提供完整的大堆和小堆调整函数实现代码,以及升序和降序排列的具体算法;6)测试结果展示了算法的正确性。时间复杂度分析表明,建堆过程为O(logN),整体排序效率较高。
2025-06-04 20:15:59
434
原创 数据结构树
节点的度:节点拥有的子树的数目。叶子:度为零的节点。分支节点:度不为零的节点。树的度:树中节点的最大的度。层次:根节点的层次为1,其余节点的层次等于该节点的双亲节点加1。树的高度:树中节点的最大层次。无序数:如果树中节点的各子树之间的次序是不重要的,可以交换位置。有序数:如果树中结点的各子树的次序是重要的,不可以交换位置。森林:0个或多个不相交的树组成。对森林加上一个跟,森林即成为树;删去跟,树即成为森林。
2025-06-03 21:02:32
295
原创 归并排序(递归和非递归)
摘要:本文介绍了归并排序的单趟排序原理及其实现方法。单趟排序通过开辟新空间合并两个有序数组,再将结果拷贝回原数组。文章详细讲解了递归实现(MergeSort)和非递归实现(MergeSort2)两种方式,其中非递归实现通过控制gap间隔逐步扩大有序区间,效率更高但需要考虑边界处理。两种实现都使用辅助数组进行合并操作,最终完成整个数组的排序。代码展示了完整的排序过程,包括区间划分、合并和边界条件处理。
2025-06-03 11:14:55
762
原创 插入排序和希尔排序
插入排序就是将第k个数插入区间[0,k-1](该区间已经是有序的)中,使之成为一个新的有序区间 [0,k]。如图将第一个数作为最开始的区间(必然是有序的),从第2个数开始依次作为k插入前面的区间中时间复杂度:o(n^2) 空间复杂度o(1)
2025-06-02 19:00:54
202
原创 快速排序递归和非递归
快速排序的核心思想是通过选取基准值(key)将数组划分为左右两个子区间,左区间小于基准值,右区间大于基准值,再递归处理子区间。文章介绍了三种单趟排序实现方法:左右指针法、前后指针法和挖坑法,以及递归和非递归的实现方式。关键点在于通过三数取中优化基准值选择,避免最坏情况下的O(n^2)时间复杂度。快速排序平均时间复杂度为O(nlogn),空间复杂度O(logn),但最坏情况下会退化为O(n^2)。该算法不稳定,且递归过深可能导致栈溢出。非递归实现通过栈结构存储待处理区间来避免递归风险。
2025-06-02 13:28:46
716
原创 C++中的内存分配和管理
程序内存布局与动态内存管理摘要 内存布局分为数据段(.data、.bss、.rodata)和代码段。数据段存储全局/静态变量,代码段存放机器指令和常量数据,具有只读特性。动态内存方面,malloc/free与new/delete存在关键差异:new会调用构造函数/析构函数,且通过异常处理失败;而malloc仅分配原始内存。内存泄漏指程序失去对已分配内存的控制,长期运行会导致系统性能下降,需特别注意资源释放。理解这些机制对编写高效、安全的程序至关重要。
2025-06-01 20:58:16
588
原创 C++中的类和对象
1. 声明和定义全部放在类体中 需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。2.类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::(做项目更通用)
2025-06-01 13:27:09
779
原创 C++的一些基础知识总结
C++库中的所以的东西都是放在std命名空间中 ,如果将命名空间全部展开,自定义变量不能于std命名空间的变量冲突。自己也可以创建命名空间,命名空间可以嵌套。
2025-05-31 17:33:15
860
原创 C++中vector的实现
本文详细介绍了vector容器的实现原理和关键操作。vector采用动态数组实现,包含三个迭代器成员变量(_start、_finish、end_of_storage)分别指向数组首元素、末元素后位置和存储空间边界。文章分析了构造函数、resize/reserve扩容机制,指出浅拷贝在vector<string>时会导致野指针问题,必须使用深拷贝。此外还阐述了push_back、insert、erase等操作的实现细节,以及operator[]的重载方式。
2025-05-31 14:57:19
1362
原创 C++中string的实现
string如其名,就是一个字符串,string的成员对象有char* _str(指向存储的字符串),size_t _size(记录该字符串所含的字符个数),size_t _capacity(该指针指向空间的大小容量)。
2025-05-30 20:45:58
478
原创 C++中List的实现
文章详细讲解了双向链表(list)的实现原理。通过定义包含前驱/后继指针和数据的_node结构体构建链表基础,并使用迭代器(_list_iterator)封装节点访问操作,支持++、--、解引用等功能。通过模板技术实现了const与非const迭代器的区分,确保类型安全。具体实现包括默认构造函数、begin/end获取、push_back尾插、erase删除、clear清空、insert插入等核心操作,并分析了迭代器传值设计的原因。最后展示了链表的打印功能,完整呈现了一个STL风格的双向链表实现框架。
2025-05-29 21:29:10
797
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人