![](https://img-blog.csdnimg.cn/20201014180756922.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
C++
文章平均质量分 67
骇城迷影
努力学编程的屋里人
展开
-
C与C++的文件读写
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。sprintf:把格式化的数据,存放在(转换成)一个字符串。ferror-返回真,就说明是文件在读取过程中出错了,而结束。feof-返回真,就说明是文件正常读取到了结束标志而结束的。fseek:根据文件指针的位置和偏移量来定位文件指针。③格式化输入函数 fscanf(适用于所有输入流)stdout - 标准输出(屏幕)类型:FILE*rewind:让文件指针的位置回到文件的起始位置。原创 2023-10-21 12:35:25 · 63 阅读 · 0 评论 -
特殊类设计
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。①构造函数私有化,在该类中声明,在类外定义一个自己类型的静态对象(不要直接定义一个该类的全局对象,因为类外面是调不了构造函数的)。1.同上将构造函数私有化,(但是不能将拷贝构造私有化,因为栈的传值返回需要调用拷贝构造)。①构造函数私有化,在该类中声明,在类外定义一个自己类型的静态对象指针并置空。2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建。原创 2023-10-17 20:07:09 · 67 阅读 · 2 评论 -
异常与智能指针
3.)C++中异常经常会导致资源泄漏的问题,比如在new和delete中抛出了异常,导致内存泄漏,在lock和unlock之间抛出了异常导致死锁,C++经常使用RAII来解决以上问题,关于RAII。1. 异常会导致程序的执行流乱跳,并且非常的混乱,并且是运行时出错抛异常就会乱跳。4. C++标准库的异常体系定义得不好,导致大家各自定义各自的异常体系,非常的混乱。抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,1、C语言传统处理错误的方式:终止程序,退出函数,返回错误码。原创 2023-10-16 00:26:12 · 68 阅读 · 0 评论 -
C++11特性
错误写法如上,返回值是ret的别名,而ret正常销毁,不会将ret识别成将亡值(只有传值返回才会触发编译器的优化)(引用返回只要不是在栈区上均可)。2.)对于拷贝构造和移动构造对象而言,emplace_back是直接构造了,push_back是先构造,再移动构造。ret2:编译器也进行了优化处理,把str识别成了右值--将亡值,先移动构造,再移动赋值。str(左值)先拷贝构造(深拷贝)后移动构造(浅拷贝),Func的返回值是右值。连续的构造/拷贝构造,合二为一,编译器把str识别成右值--将亡值。原创 2023-10-14 21:37:06 · 78 阅读 · 3 评论 -
STL篇:哈希原理以及实现
不扩容,不断插入,某些桶越来越长,效率得不到保障。解决方式:闭散列开放定址法:当前位置被占用了,按规则找下一个位置(占用别人的位置)但是会引发哈希冲突碰撞不同的值可能会映射到同一个位置,值和位置是多对一的关系。3、哈希表不能满了再扩容,控制负载因子(0.7~0.8)到一定值就扩容。负载因子越小,冲突概率越小,空间利用率越低(空间浪费越多)1、载荷/负载因子=填入表中的元素个数/散列表的长度。负载因子越大,冲突概率越大,空间利用率越高。1、直接定值法(值的分布范围集中)2、除留余数法(值的分布范围分散)原创 2023-09-24 21:37:35 · 210 阅读 · 2 评论 -
STL篇:用红黑树模拟实现封装set与map
【代码】STL篇:用红黑树模拟实现封装set与map。原创 2023-09-24 21:14:57 · 58 阅读 · 1 评论 -
STL篇:搜索二叉树,AVL树和红黑树的模拟实现
更新后parent平衡因子=0,说明parent所在的子数的高度不变,不会再影响祖先,不用再继续(沿着到root的路径)往上更新。更新后parent平衡因子=-1/1,说明parent所在的子数的高度变化,会影响祖先,需要继续(沿着到root的路径)往上更新。更新后parent平衡因子=-2/2,说明parent所在的子树的高度变化且不平衡,对parent所在的子树进行旋转,使之平衡。b.左右子树高度之差(简称平衡因子)的绝对值不超过1(平衡因子=右子树的高度-左子树的高度)b.黑色节点占比>=1/2。原创 2023-09-17 10:40:52 · 197 阅读 · 4 评论 -
尽信书不如无书,用实践学透继承与多态底层
答,不能因为静态成员函数没有this指针使用类型成员函数的调用方式无法访问虚函数表,所以静态成员函数无法放进虚函数表,无法实现出多态,也就没有意义,所以语法会强制检查。答:首先,如果是普通对象是一样快的,如果是指针对象或者引用对象,则调用的普通函数快,因为构成多态运行时调用虚函数,需要到虚函数表中去查找。虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型函数名字参数列表完全相同),称子类的虚函数重写了基类的虚函数。什么场景下,虚构函数是虚函数?原创 2023-08-08 21:04:30 · 177 阅读 · 5 评论 -
STL篇:堆与优先级队列
向下调整建堆条件是左右子树均是大/小堆(所以从倒数第一个非叶子节点开始调整),这种方法的效率比向上调整建堆效率高。向下调整建大堆:从倒数第一个非叶子节点开始调整(大的向上调整,小的向下调整)(时间复杂度:logn)5、topk问题:找最大的前k个数,要(将前k个数)建小堆,交换头尾,再将头向下调整。错误:建小堆,如果挪动删除,剩下的看作堆,选次小的,但是关系乱了,得重新建堆。正确方式:交换头尾,pop掉尾,头向下调整(哪个儿子大,调哪个)正确:建大堆,交换,向下调整(跟删除数据一样的思路)原创 2023-08-05 20:15:40 · 268 阅读 · 3 评论 -
STL篇:用容器适配器实现栈和队列
3、头尾插删两者都不错,但中间插入删除deque很拉胯(所以deque用来适配stack和queue的默认容器再合适不过了)stack(后进先出)和queue(先进先出)均为容器适配器,适配器的本质是复用。deque:通过中控(指针数组)控制数据。若指针数组满,则中控指针扩容即可。2、[]不够机极致,需计算在哪个buff数组,在哪个buff数组的第几个。链表:任意位置插入删除都可以,按需申请释放,不支持下标随机访问。顺序表:下标随机访问扩容问题。1、极大地缓解了扩容问题/头插头删问题。原创 2023-08-05 15:15:15 · 74 阅读 · 1 评论 -
STL篇:vector的用法注意事项以及模拟实现
vector是深拷贝,但是vector空间上存的对象是string的数组,使用memcpy导致string对象的浅拷贝。string:要求最后有“\0”,更好地兼容c接口,它有很多它的专用接口(+=,比较大小等)3、错误用法:有空间不一定能访问(reserve,resize之前必须初始化)1、vector的用法与string相似,不再赘述。4、二维数组vector5、迭代器区间:左闭右开[first,last)vector:没有“\0”,比较大小无意义。原创 2023-08-04 11:51:54 · 97 阅读 · 3 评论 -
STL篇:list的用法注意事项以及模拟实现
forward iterator单向(++):forward_list(单链表)/unordered_xxx(哈希)Random access iterator随机(++/--/+/-):vector/string/deque。4、迭代器对象不写析构函数,因为迭代器仅用于访问容器,节点不属于迭代器,不需要迭代器释放。bidirectional Iterator双向(++/--):list/map/set。3、迭代器根据性质(容器底层结构)决定。insert后,迭代器it不失效。原创 2023-08-03 22:16:35 · 97 阅读 · 3 评论 -
STL篇:string的用法及模拟实现
在VS2019中,若字符串size=16,则存在_ptr指向的堆空间中。2、一个对象修改影响另一个(延迟拷贝解决):写的时候引用计数如果不是1,则进行深拷贝,再修改。1、析构两次(引用计数解决):最后一个管理此块空间的对象对其析构(最后一个走的人关灯)push_back(尾插字符),append(尾插字符串)与assign(覆盖)clear:只清数据,底层判断是否缩容(看编译器)(一般不缩)insert(插入)与erase(清除)原创 2023-08-02 20:32:15 · 65 阅读 · 3 评论 -
模板:编程界的活字印刷术
1、函数模板根据调用,自己推导模板参数的类型,实例化出对应的函数(自定义类型也可以)而用类模板实现栈时,需类里定义,类外声明(模板参数也要声明)显然,template的作用范围是模板下面第一个类/函数。2、通过实参传递的类型推演T的类型,可能会推导歧义。解决方法:显示实例化:Add<int>()(有些函数无法自动推,只能显示实体化)(不分离也可以,就是难看概况)普通类,类名和类型是一样。类模板,类名和类型不一样。类型:Stack<T>原创 2023-08-01 15:48:36 · 53 阅读 · 2 评论 -
new和delete——动态内存管理的新玩法
6.申请自定义类型对象时, malloc/free只会开辟空间, 不会调用构造函数与析构函数, 而new 在申请空间后会调用构造函数完成对象的初始化, delete在释放空间前会调用析构函数完成空间中资源的清理。5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空, new不需要, 但是new需要捕获异常(面向对象语言处理失败,不喜欢用返回,更建议用抛异常)。4. malloc的返回值为void*, 在使用时必须强转, new 不需要,因为new后跟的是空间的类型。malloc:开空间。原创 2023-07-26 11:03:41 · 86 阅读 · 9 评论 -
隐式类型转换、static成员、匿名对象
静态成员变量,属于类,属于类的每个对象共享,存储在静态区。静态成员,没有this指针(不能访问非静态成员),只要突破/指定类域和访问限定符/友元,就 可以访问。静态不可以调用非静态(非静态的成员函数调用需要this指针,而静态没有),非静态可以调用 静态。静态成员变量不能给缺省值(因为他没有初始化列表)(缺省值是给初始化列表的)。静态成员在类里面声明,类外面定义,且不受访问限定符的限制。成员变量属于每个类对象,存储在对象里。静态成员函数和静态成员变量配套出现。原创 2023-07-23 20:51:28 · 58 阅读 · 0 评论 -
用日期计算器通杀运算符重载
Date和MyQueue不需要我们自己实现赋值重载,Date是内置类型成员,Myqueue是自定义类型成员。赋值运算符只能重载成类的成员函数,不能重载成全局函数(否则冲突)(就像亲儿子只能在家吃饭)(也可以在类里面给声明,类外面给定义)总结:只要成员函数内部不修改成员变量,都应该加const,这样const对象和普通对象都可以调用。用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝,相当于拷贝构造。cin是istream类型的对象(流提取和流插入一样,不能用const修饰)原创 2023-07-21 20:43:45 · 65 阅读 · 3 评论 -
探究全自动化机器——构造与析构的奥秘
无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个,所以无参构造函数、全缺省构造函数,我们没写编译器默认生成的构造函数都可以认为是默认构造函数,不传参就可以调用的,就是默认构造函数。类的6个默认成员函数(我们不写,编译器自动生成):构造函数,析构函数,拷贝构造,赋值重载,普通对象和const对象取地址。我们不写,编译器默认生成的构造函数,内置类型不做处理(有些编译器也会处理),自定义类型会去调用他的默认构造。没有动态申请的资源,不需要写析构,需要释放资源的成员,不需要写析构。原创 2023-07-21 14:35:58 · 78 阅读 · 2 评论 -
类和对象一镜到底
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。this指针(形参)存在栈上,作为栈帧的一部分。类中成员变量若不开空间则为声明,若开空间则为定义(整体定义)(类实例化对象/对象定义)2、声明与定义分离:声明放在类的头文件(.h)中,定义放在类的实现文件中(.cpp)注意:对齐数=编译器默认的一个对齐数与该成员大小的较小值(VS中默认的对齐数为8)空类:没有成员变量的类(大小为1,为了占位,表示对象存在)原创 2023-07-20 23:24:29 · 78 阅读 · 8 评论 -
宏函数与内联函数的爱恨情仇
默认debug模式下,inline不会起作用,否则不方便调试(汇编中没call说明未否决)3、inline对于编译器仅仅是一个建议,最终是否成为inline,编译器自己决定。不需要建立栈帧,提高调用效率,简单,不易出错,可读性好,容易调试。1、宏函数:不传参,无return,不加“;2、内联函数inline(适用于短小的频繁调用的函数)内联函数声明和定义不能分离(直接全写在.h中)缺点:复杂,容易出错,可读性差,不能调试。优点:不需要建立栈帧,提高调用效率。缺点:代码膨胀(可执行程序变大)原创 2023-07-20 21:49:44 · 57 阅读 · 1 评论 -
C++入门级教程:引用的超超超详细攻略
局部对象用引用返回(不会报错,就像越界不一定报错):销毁空间,归还使用权后,后续相当于野指针访问,结果打印为随机值(如果函数结束,栈帧销毁,但没有清理栈帧,那么结果侥幸是正确的)如:(栈帧覆盖)谨慎用引用做返回值,出了函数作用域,对象不在了就不能引用返回,还在或全局对象或malloc就可以用引用返回。3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体。6.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小。3、引用做返回值(减少拷贝提高效率)原创 2023-07-20 21:24:41 · 119 阅读 · 4 评论 -
C++入门级教程:我将告诉你有关域的一切
注:若展开了命名空间域,则该命名空间域暴露于全局,若与原全局域中变量同名,则不能同时存在。注:默认先从局部搜索,若局部没有,则全局搜索,如果两个都存在,则访问全局域时,要使用::(域作用限定符)1、局部域—>全局域—>展开命名空间域or指定访问命名空间域(默认:不指定是不会去命名空间域搜索的)而展开命名空间域是指,编译时去命名空间中搜索(相当于把墙拆了)在C++中,如果想访问全局域,则需要使用::(域作用限定符)几种常见的域:类域、命名空间域、局部域、全局域。2、常见误区:展开命名空间域≠include。原创 2023-07-20 17:00:04 · 266 阅读 · 2 评论