![](https://img-blog.csdnimg.cn/20201014180756738.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
C++从入门到掌握
文章平均质量分 87
对于C++的学习之路的分享
Dream_Snowar
这个作者很懒,什么都没留下…
展开
-
[C++进阶&数据结构]二叉搜索树
对于二叉树的结点,我们类似于list的结点定义一样,使用一个struct类。原创 2024-08-07 10:53:46 · 1259 阅读 · 0 评论 -
[C++进阶]继承和多态的选择题
子类定义的虚函数的新的行为会操作a变量,在子类初始化时根据构造函数调用顺序会首先调用父类构造函数,那么虚函数回去操作a,而因为a是子类成员变量,这时a尚未初始化,这是一种危险的行为,作为一种明智的选择应该禁止这种行为。C. 选择题一定要扣字眼,题目前半句说的是基类引用 引用了子类对象,但是后半句调用虚函数时,说的是基类的对象调用f2,通过对象调用时编译期间就直接确定调用那个函数了,不会通过虚表以多态方式调用。C.A::f(),因为强制类型转化后,生成一个基类的临时对象,pa实际指向的是一个基类的临时对象。原创 2024-07-31 01:31:09 · 663 阅读 · 0 评论 -
[C++进阶]抽象类
在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。至于为什么起这个抽象的名字,我们可以理解为,这个类在现实世界中没有实体。所以不能实例化出对象。而且由于派生类继承了抽象类,它里面也包含了纯虚函数,那么它自然也不能实例化出对象了。原创 2024-07-29 08:42:26 · 366 阅读 · 0 评论 -
[C++进阶]对于多态的底层逻辑
在前面我们也已经提到过,在语法层面称之为重写,重写的是它的实现。所以有时候我们也会提出一个概念,普通的函数的继承称为实现继承,而多态,虚函数的重写,其实就是一个接口继承,然后重写它的实现在原理上就是说将父类的虚函数表给拷贝下来,然后将子类中重写的部分给覆盖。其次,因为只有完成了虚函数的重写,那派生类的虚表里面才能是派生类的虚函数。这样的话,这个基类指针才能做到指向父类调用父类,指向子类调用子类。原创 2024-07-29 00:00:14 · 1129 阅读 · 0 评论 -
[C++进阶]多态的概念、定义与实现
多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。那么在继承中要构成多态还有两个条件:必须通过基类的指针或者引用调用虚函数被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写。多态的实现有两个条件必须通过基类的指针或者引用调用虚函数被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写(也就是要调用重写的虚函数)。原创 2024-07-26 01:11:34 · 956 阅读 · 0 评论 -
[C++进阶]多继承和菱形继承
很多人说C++语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设计出菱形继承。否则在复杂度及性能上都有问题。多继承可以认为是C++的缺陷之一,很多后来的OO(OO是面向对象,OOP是面向对象程序设计)语言都没有多继承,如Java。原创 2024-07-23 00:25:45 · 635 阅读 · 0 评论 -
[C++进阶]继承
Person类称为基类(父类),Student类称为派生类(子类)继承方式为public(公有)继承。原创 2024-07-22 17:03:05 · 669 阅读 · 0 评论 -
[C++进阶]模板进阶
class 类模板名 {};T* _finish;原创 2024-07-21 23:04:39 · 1069 阅读 · 2 评论 -
[C++]优先级队列
优先级队列是一种容器适配器,根据一些严格的弱排序标准,专门设计使其第一个元素始终是它所包含的元素中最大的元素。此上下文类似于堆,其中可以随时插入元素,并且只能检索最大堆元素(优先级队列中顶部的元素)。优先级队列是作为容器适配器实现的,容器适配器是使用特定容器类的封装对象作为其底层容器的类,提供一组特定的成员函数来访问其元素。元素是从特定容器的“背面”弹出的,该容器称为优先级队列的顶部。基础容器可以是任何标准容器类模板,也可以是其他一些专门设计的容器类。原创 2024-07-19 23:27:54 · 1096 阅读 · 0 评论 -
[C++初阶]deque的讲解
Deque是双端队列的不规则缩写。双端队列是具有动态大小的序列容器,可以在两端扩展或收缩。特定的库可能以不同的方式实现deque,通常是某种形式的动态数组。在任何情况下,它们都允许通过随机访问迭代器直接访问单个元素,并根据需要通过扩展和收缩容器来自动处理存储。因此,它们提供了类似于向量的功能,但在序列的开始,而不仅仅是在序列的末尾,也可以有效地插入和删除元素。但是,与vector不同,deque不能保证将其所有元素存储在连续的存储位置:通过偏移指向另一个元素的指针来访问deque中的元素会导致未定义的行为。原创 2024-07-19 01:14:44 · 872 阅读 · 0 评论 -
[C++]一些list,stack和queue选择题和编程题
这时我们学完后的应用1.下面有关vector和list的区别,描述错误的是( )A.vector拥有一段连续的内存空间,因此支持随机存取,如果需要高效的随机存取,应该使用vectorB.list拥有一段不连续的内存空间,如果需要大量的插入和删除,应该使用listC.vector<int>::iterator支持“+”、“+=”、“<”等操作符D.list<int>::iterator则不支持“+”、“+=”、“<”等操作符运算,但是支持了[ ]运算符。原创 2024-07-16 23:17:36 · 929 阅读 · 0 评论 -
[C++]reverse_iterator的封装实现
反向迭代器适配器(reverse_iterator),可简称为反向迭代器或逆向迭代器,常用来对容器进行反向遍历,即从容器中存储的最后一个元素开始,一直遍历到第一个元素。值得一提的是,反向迭代器底层可以选用双向迭代器或者随机访问迭代器作为其基础迭代器。当反向迭代器执行 ++ 运算时,底层的基础迭代器实则在执行 -- 操作,意味着反向迭代器在反向遍历容器;当反向迭代器执行 -- 运算时,底层的基础迭代器实则在执行 ++ 操作,意味着反向迭代器在正向遍历容器。原创 2024-07-16 15:01:59 · 196 阅读 · 0 评论 -
[c++初阶]stack和queue的使用以及模拟实现
区别于vector等容器,stack是一种容器适配器。通俗的讲,stack封装了一个其他的容器,并提供特定的成员函数来对容器进行操作并遵循栈的后进先出(Last-in First-out)原则。stack的底层容器至少要支持以下操作:empty:判空size:获取容器有效元素个数back:获取容器尾部元素push_back:尾插pop_back:尾删通过这些操作,我们就可以实现栈的压入和弹出等行为。原创 2024-07-16 00:57:50 · 871 阅读 · 0 评论 -
[C++初阶]list的模拟实现
首先,我们一开始最先看到的就是这个结点的结构体,在这里我们可以注意到这是一个双向链表。有一个前驱指针,一个后继指针。然后在有一个存储数据的空间其次它的迭代器是一个自定义类型,而非原生指针。这里我们先不管,我们接着往下看。我们继续找成员变量,在这里我们就找到了成员变量,但是这个类型我们看不懂,于是我们先略过。通过对定义的查找,可以看到这个实际上还是一个指针。但是这个指针我们还是看不懂。于是我们继续去速览定义,于是就找到了这里。原创 2024-07-14 20:21:37 · 1266 阅读 · 0 评论 -
[C++初阶]list类的初步理解
并且在C++文档中,我们可以看到标准库中的sort也限定了迭代器的类型必须是可以进行随机访问(RandomAccess)的。实际上list的迭代器并不是用原生态指针进行模拟实现的,需要进行底层的封装,这里会在list的模拟实现的源代码中体现。但是list的删除操作一定会导致迭代器失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。list由于结构的特殊性,是无法使用标准库中的sort函数的,因为迭代器无法进行相减的操作。(请注意,此函数通过插入或擦除容器中的元素来更改容器的实际内容。原创 2024-07-10 10:59:08 · 979 阅读 · 0 评论 -
[C++初阶]vector的模拟实现
上篇我们实现了STL学习的三步:能用,明理,能扩展中的能用,着篇我们要办到明理。所以,本篇,我们将会对于vector进行模拟实现。这里我们采用和之前一样的方法自己开一个命名空间,写出我们自己的vector类像这样。原创 2024-07-06 00:28:34 · 916 阅读 · 0 评论 -
[C++初阶]vector的oj
将快指针 fast 依次遍历从 1 到 n−1 的每个位置,对于每个位置,如果 nums[fast]=nums[fast−1],说明 nums[fast] 和之前的元素都不同,因此将 nums[fast] 的值复制到 nums[slow],然后将 slow 的值加 1,即指向下一个位置。由于给定的数组 nums 是有序的,因此对于任意 i<j,如果 nums[i]=nums[j],则对任意 i≤k≤j,必有 nums[i]=nums[k]=nums[j],即相等的元素在数组中的下标一定是连续的。原创 2024-07-08 20:36:04 · 726 阅读 · 0 评论 -
[C++]迭代器失效
如果pos刚好对应最后一个元素,删除后迭代器pos就超出了有效元素范围,可能导致非法访问,属于迭代器失效。以上函数在使用时都可能会导致vector扩容,在扩容时原空间会被释放,迭代器就会指向一块被释放的空间。假设有迭代器pos,使用pos删除pos对应位置的元素后,该迭代器对应的元素发生改变,属于迭代器失效。当迭代器底层的指针指向的空间被销毁时,如果继续在程序中使用该迭代器,就会造成程序崩溃,这就是。迭代器失效后,如果我们需要继续使用迭代器,给迭代器重新赋值即可。本篇是对于vector的那篇章的补充。原创 2024-07-04 16:48:52 · 171 阅读 · 0 评论 -
[C++初阶]vector的初步理解
1. vector是表示可变大小数组的序列容器和数组一样,vector可采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。2. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小,以增加存储空间。其做法是:分配一个新的数组,然后将全部元素移到这个数组。原创 2024-07-04 00:56:58 · 1197 阅读 · 0 评论 -
[C++初阶]string类的详解
//string.cpp现在我们看到的是,我这边写的,接下来我将会对于这些内容进行解析,首先我这边的模拟实现都是基于理解和string。 2.string类的定义和迭代器1)私有成员这里的内容比较少。2)公有成员3)迭代器我们都知道在string中我们常常使用迭代器来完成不少操作,我们知道迭代器其实就是一种指针,所以这里我们选择这样实现3.构造函数声明:这里我们选择用缺省函数保证字符串内容下面是搞函数的内部实现:首先我们用列表初始化得出原创 2024-06-09 14:32:05 · 846 阅读 · 0 评论 -
[C++初阶]string的几道oj题
然后我们把它尾插入我们创建的新的string中(这里我选择采用尾插,但也可以用头插(但是头插的时间复杂度更高,因为每次头插都要移动位置))同时我们一块定义好我们的进位值,因为我们进行的是10进制计算。注意:我们要判断是否超过了int的最大值或最小值,而且要保证自己的int类型不超过int的最大值或最小值。如果超出了最值,我们接下来通过symbol的值来判断是最大值还是最小值,然后返回相应结果。如果读完了所有的数,都没有超出最值,那么我们直接调用上面我们写的公式返回。判断此时读入的是否为数字,是数字则读入。原创 2024-05-08 21:44:19 · 1009 阅读 · 6 评论 -
[C++初阶]string类
nposnpos的值通常是一个很大的正数,等于-1(当作为无符号数解释时或等于string::size_type的最大可能值。原创 2024-05-04 12:38:59 · 1063 阅读 · 6 评论 -
[C++初阶]STL的介绍
STL是C++编程语言中的一个重要组成部分,它提供了一系列标准化的模板类和函数,旨在简化程序设计,提高代码的复用性和可维护性。4. STL的使用会有代码膨胀的问题,比如使用vector/vector/vector这样会生成多份代码,当然这是模板语法本身导致的。STL的设计思想是将数据结构和算法分离,这样可以灵活地将不同的算法应用于不同的数据结构上,从而提高编程效率和代码的可读性。中的优秀作品,有了它的陪伴,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发。原创 2024-04-30 19:46:02 · 290 阅读 · 5 评论 -
[C++初阶]模板初阶
函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数。函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定。如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。巧的是前人早已将树栽好,我们只需在此乘凉。2. 代码的可维护性比较低,一个出错可能所有的重载均出错。,对于字符类型也是如此。,对于模板函数的使用,原创 2024-04-26 22:20:49 · 298 阅读 · 6 评论 -
[C++初阶]内存管理的几道选择题
分析:首先手动释放pa, 所以会先调用A的析构函数,其次会跟定义相反的顺序释放局部对象,这里只有b,就释放b,再释放静态局部对象d,再释放全局对象c。A.栈区主要存在局部变量和函数参数,其空间的管理由编译器自动完成,无需手动控制,堆区是自己申请的空间,在不需 要时需要手动释放。B.new 初始化对象,调用对象的构造函数,对应的delete调用相应的析构函数,malloc仅仅分配内存,free仅仅回收内存。B.栈区先定义的变量放到栈底,地址高,后定义的变量放到栈顶,地址低,因此是向下生长的,堆区则相反。原创 2024-05-04 19:09:50 · 374 阅读 · 4 评论 -
[C++初阶]C++内存管理
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常, malloc会返回NULL。申请空间失败, 尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。2. 在申请的空间上执行N次构造函数。原创 2024-04-26 20:40:51 · 955 阅读 · 2 评论 -
[C++初阶]一些类的选择题
A.友元函数不是类的成员函数,就相当于你的朋友再亲密也不是你的家人,既然不是类成员函数,那和普通成员函数调用一样,不需要通过对象调用。A.初始化顺序由定义类时的声明顺序决定,所以先初始化_a2,由于初始化_a2时_a1还未初始化,所以为随机值,故错误。B.友元的目的就是为了访问类的私有数据,成员函数可以直接访问类的私有数据。B.友元函数和类的成员函数都可以访问类的私有成员变量或者是成员函数。C.类的成员函数是属于类的,调用的时候是通过指针this调用的。6.下面有关友元函数与成员函数的区别,描述错误的是?原创 2024-04-25 22:34:44 · 323 阅读 · 4 评论 -
[C++初阶]日期类
前面我们讲过了类和对象,现在我们来建立一个日期类来实践一下吧。原创 2024-04-25 16:02:14 · 780 阅读 · 8 评论 -
[C++初阶]类和对象(三)
类是对某一类实体(对象)来进行描述的,描述该对象具有那些属性,那些方法,描述完成后就形成了一种新的自定义类型,才用该自定义类型就可以实例化具体的对象。原创 2024-04-22 20:54:21 · 1181 阅读 · 10 评论 -
[C++]类和对象(二)
而_t是Time类对象,所以在d销毁时,要将其内部包含的Time类的_t对象销毁,所以要调用Time类的析构函数。但是,main函数中不能直接调用Time类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函数,而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,目的是在其内部调用Time类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析构函数。原创 2024-04-21 21:33:32 · 974 阅读 · 10 评论 -
[C++初阶]类和对象(一)
1. 声明和定义全部放在类体中,需注意:成员函数如果。原创 2024-04-16 13:54:23 · 851 阅读 · 12 评论 -
[C++初阶]初识C++(二)
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。我们可以举个例子:比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。铁牛,黑旋风,都是李逵的别名。写法是用&符号修饰,类型& 引用变量名(对象名) = 引用实体;原创 2024-04-06 00:03:25 · 746 阅读 · 2 评论 -
[C++初阶]初识C++(一)—————命名空间和缺省函数
在编程语言中,命名空间是一种特殊的作用域,它包含了处于该作用域中的所有标示符,而且其本身也是由标示符表示的。命名空间的使用目的是为了将逻辑相关的标示符限定在一起,组成相应的命名空间,可使整个系统更加模块化,最重要的是它可以防止命名冲突。就好比在两个函数或类中定义相同名字的对象一样,利用作用域标示符限定该对象是哪个类里定义的。定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员// 命名空间中可以定义变量/函数/类型。原创 2024-04-03 22:56:17 · 807 阅读 · 4 评论