![](https://img-blog.csdnimg.cn/20201014180756930.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
c++
文章平均质量分 94
c++博客
只是雪豹
大三fw一枚
展开
-
特殊类设计以及C++中的类型转换
如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。就比如说:如果单例1和单例2同时创建,那么饿汉模式就无法控制顺序了,并且如果当单例对象过大时,main函数前就要申请资源,占用了资源,程序的启动就会变慢。,如果非强制类型转换不可,则应限制强制转换值的作用域,以减少发生错误的机会。原创 2024-03-13 20:08:08 · 1138 阅读 · 4 评论 -
智能指针的讲解
内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。那么内存泄漏对于程序又会有什么样的危害呢?如果说这只是一个小小的代码段,它的影响其实不大,但是如果是在像操作系统这样的程序中发生内存泄漏那危害还是蛮大的长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。原创 2024-03-13 16:22:32 · 1009 阅读 · 1 评论 -
异常的讲解
其实异常的规范很多人都不会用的,实际使用中很多公司都会自定义自己的异常体系进行规范的异常管理,因为一个项目中如果大家随意抛异常,那么外层的调用者基本就没办法使用了,所以实际中都会定义一套继承的规范体系。这样大家抛出的都是继承的派生类对象,捕获一个基类就可以了// 服务器开发中通常使用的异常继承体系public:,_id(id){}protected:int _id;原创 2024-03-12 17:08:11 · 1118 阅读 · 4 评论 -
C++11的简单介绍(下)
在C++11之前,涉及到多线程问题,都是和平台相关的,比如windows和linux下各有自己的接口,这使得代码的可移植性比较差。C++11中最重要的特性就是对线程进行支持了,使得C++在并行编程时不需要依赖第三方库,而且在原子操作中还引入了原子类的概念。要使用标准库中的线程,必须包含< thread >头文件。kw=thread线程是操作系统中的一个概念,线程对象可以关联一个线程,用来控制线程以及获取线程的状态。当创建一个线程对象后,没有提供线程函数,该对象实际没有对应任何线程。原创 2024-03-10 20:32:35 · 1259 阅读 · 13 评论 -
C++11的简单介绍(上)
在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于C++03(TC1)主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。从C++0x到C++11,C++标准10年磨一剑,第二个真正意义上的标准珊珊来迟。相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正。原创 2024-03-10 17:53:56 · 887 阅读 · 0 评论 -
哈希图的应用
这个题目我们就用一个哈希函数进行切割,将这个100g的log file分成若干个小的文件,然后再对依次对这些小文件进行处理,使用map统计每个小文件里每个ip出现的次数,然后提取出每个map中的出现次数最多的ip,和其他小文件的出现次数最多的比较,选出最大的一个ip。1往做移动j位后取反,就只有第j位为0,其他位置都为1,与上第i个位置,第j个位置无论是0还是1都会置为0,其他位置是0就变为0,是1还是1。如果要删除某个位置,就要将它置零,所以第i个位置的整形与上1往左边移动j位后取反的结果,原创 2024-03-07 16:20:37 · 1131 阅读 · 16 评论 -
哈希的简单介绍
unordered_map是存储<key, value>键值对的关联式容器,其允许通过keys快速的索引到与其对应的value。在unordered_map中,键值通常用于惟一地标识元素,而映射值是一个对象,其内容与此键关联。键和映射值的类型可能不同。在内部,unordered_map没有对<kye, value>按照任何特定的顺序排序, 为了能在常数范围内找到key所对应的value,unordered_map将相同哈希值的键值对放在相同的桶中。原创 2024-03-05 14:03:36 · 1364 阅读 · 12 评论 -
用红黑树封装实现map和set
对红黑树类型中的迭代器类型进行typedef时,可以看到我们在typedef后面加了typename,typename的作用就是告诉编译器后面的东西是一个类型,你先不要编译他,等到模板实例化为真正类型后,你再去取他里面的内嵌类型iterator。,只有模板实例化之后,它里面的内嵌类型我们才可以取到,所以如果你不加typename,有可能取的不是类型,因为静态变量或函数都是可以通过类+域访问符进行访问的,所以如果你要取模板里面的类型,那就必须在模板前面加typename,告诉编译器你取的是类型。原创 2024-03-05 09:58:00 · 996 阅读 · 4 评论 -
红黑树的简单介绍
根据上面的红黑树的性质和我们之前学习的AVL树的知识的铺垫,我们就可以很快的将红黑树的基本框架搭起来:与AVL树的平衡因子不同,红黑树除了节点外还要枚举节点的颜色我们将黑色和红色先进行枚举// 红黑树节点的定义{}// 节点的左孩子// 节点的右孩子// 节点的双亲(红黑树需要旋转,为了实现简单给出该字段)// 节点的值域// 节点的颜色大家可以看到我们在节点的颜色的初始化时的时候给了缺省参数是红色,这是为什么呢?大家可以想一想,原创 2024-03-04 20:23:39 · 939 阅读 · 46 评论 -
AVL 树
AVL树是一种特殊的二叉搜索树,它具有高度的平衡,所以为了在插入过程中的各个节点的平衡因子的更新,我们在定义AVL树的节点结构的同时要带上一个节点的双亲结点parent{}// 该节点的左孩子// 该节点的右孩子// 该节点的双亲T _data;int _bf;// 该节点的平衡因子。原创 2024-03-01 19:25:26 · 1027 阅读 · 18 评论 -
map和set的简单介绍
map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:在内部,map中的元素总是按照键值key进行比较排序的。原创 2024-02-29 16:19:09 · 1370 阅读 · 7 评论 -
二叉树进阶之二叉搜索树
当删除节点既有左孩子又有右孩子的时候我们面对的问题就是他被删除后他的两个孩子节点怎么办,这个时候我们就有两种解决的办法,一个是找一个左子树的最大节点,另一种办法就是找右子树的最小节点来替代这个被删除的节点的值,这种情况不同于上面两种情况,我们叫做替代删除。其实插入的节点到最终都是一个叶子节点,所以二叉搜索树的插入还是很简单的,就比如我要插入0和16,最终都是成为这棵树的新的叶子节点。下图中打x叉的就不是二叉搜索树,因为第三层的5小于他的父节点10,打勾的就是二叉搜索树,它满足了二叉搜索树的所有条件。原创 2024-02-27 20:36:53 · 931 阅读 · 8 评论 -
多态的讲解
多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。必须通过基类的指针或者引用调用虚函数被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写如果是对象直接调用的话就不会构成多态,上图中的虚函数覆盖就是我们所说的虚函数重写,其实覆盖是底层实现上的理解,而重写是语义上的理解,我们在后面也会对其讲解注意:重载是函数名相同参数不同。原创 2024-02-26 20:32:52 · 843 阅读 · 24 评论 -
C++中的继承
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。原创 2024-02-04 17:57:40 · 1354 阅读 · 25 评论 -
模板讲解之进阶
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。【优点】模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生增强了代码的灵活性【缺陷】模板会导致代码膨胀问题,也会导致编译时间变长出现模板编译错误时,错误信息非常凌乱,不易定位错误。原创 2024-02-02 16:08:07 · 1276 阅读 · 15 评论 -
stack和queue及优先级队列和适配器(包括deque)的介绍
stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:empty:判空操作back:获取尾部元素操作push_back:尾部插入元素操作。原创 2024-02-02 12:38:01 · 1343 阅读 · 31 评论 -
list的介绍及其模拟实现
list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。原创 2024-01-25 20:56:05 · 1348 阅读 · 29 评论 -
string类的函数讲解
至于容量为什么是15,这就是底层实现的原因了,一些编译器是基于1.5倍的扩容,比如我们的vscode,而linux的终端里是以2倍的扩容,其实不必太过于纠结这一点,我们只需要了解到这一点即可。这里要引出的是 reverse_iterator 其实这里的rbegin已经不在字符串的第一个位置了二者是有区别的,并且,这里的指针也是++,不然怎么会叫做反向迭代器呢?我们这里的size和lenth的作用是一样的,只是在后期的语言发展中为了适应需要,例如,如果是一个二叉树,用lenth合适吗,所以就引出了size。原创 2023-12-26 19:36:42 · 1655 阅读 · 51 评论 -
vector的模拟实现
上一篇我们对vector一些常用的函数进行了讲解,本篇博客我们就对vector进行模拟实现,以便于我们更好地了解vector的使用以及对一些常见bug的认识有了string类的模拟实现,vector的模拟实现我们上手起来就简单一点了:首先为了和库里面的vector混淆视听,放入自己命名的空间里,并且根据vector的源码分析我们得出了三个成员变量:分别是:其实他们实质上都是指针,位置大概是这样的,遵循左闭右开的规则这样一个简单的框架就构造出来了:template是模板初阶我们学习过的,里面的T原创 2024-01-22 18:09:04 · 1177 阅读 · 19 评论 -
vector讲解
vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。原创 2024-01-21 10:05:43 · 1204 阅读 · 38 评论 -
string类的模拟实现
上一篇博客我们对string类函数进行了讲解,今天我们就对string类进行模拟实现,以便于大家更加深入地了解string类函数的应用然后就是我们将string类的类的成员进行定义:string类实际就是字符串,它的几个成员有capacity(容量),size(字符拆串当前字符个数),str(字符串的指针)原创 2024-01-20 09:39:30 · 1157 阅读 · 30 评论 -
C++内存管理和模板初阶
new的原理调用operator new函数申请空间在申请的空间上执行构造函数,完成对象的构造delete的原理在空间上执行析构函数,完成对象中资源的清理工作调用operator delete函数释放对象的空间new T[N]的原理调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请在申请的空间上执行N次构造函数delete[]的原理在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理。原创 2023-12-23 18:16:24 · 1816 阅读 · 23 评论 -
类和对象(下篇)
在之前的学习中我们知道,在创建一个对象时,我们的编译器就会自动调用构造函数将对象初始化,给对象中各个成员变量一个合适的初始值。例如:虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。所以C++就引入了初始化列表的概念:初始化列表的形式如下:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。废原创 2023-12-22 18:52:10 · 2872 阅读 · 45 评论 -
类和对象(上篇)
类的形式如下:这里的 classname 就是你要定义的类名class 就是定义类的关键字{}里面就是类的主题部分// 类体:由成员函数和成员变量组成// 一定要注意后面的分号类体中内容称为类的成员;类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。其实咱们可以尽量地使用第二种成员变量命名规则的建议:首先我们放上一段代码这里的形参和成员变量都长一样,就会有点僵硬。原创 2023-12-18 19:50:07 · 1675 阅读 · 52 评论 -
类和对象(中篇)
4. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?当然像日期类这样的类是没必要的。那么下面的类呢?验证一下试试?请看代码:原创 2023-12-20 20:39:05 · 2821 阅读 · 45 评论 -
C++入门
我们来看一下命名空间的定义:定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。例如:这里的myspace就是咱们自己定义的命名空间,里面的rand就可以正常使用了// 命名空间中可以定义变量/函数/类型int val;这里注意:命名空间可以嵌套使用:我们在命名空间N1中嵌套了N2int a;int b;int c;int d;原创 2023-12-10 21:59:08 · 716 阅读 · 60 评论