
C++
文章平均质量分 95
C++
搬砖狗(●—●)
这个作者很懒,什么都没留下…
展开
-
vector模拟实现
对空间进行扩容,如果n<capacity,就什么也不做,如果n>capacity,就进行扩容,新开辟一个空间,将原空间数据拷贝过来,在释放掉原空间,最后让_start,_finish,_end_of_sorage指向新空间即可。传统写法:首先判断是否是给自己赋值,若是给自己赋值则无需进行操作。vector中有三个成员变量,_start,_finish,_end_of_sorage,其中_start指向容器最开始的位置,_end_of_sorage指向容器最结尾的位置,_finish指向有效数据结尾的位置。原创 2023-08-07 19:12:29 · 149 阅读 · 0 评论 -
C++内存管理
38 int _a;39 };49 50 }new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数。new的原理调用operator new函数申请空间。在申请的空间上执行构造函数,完成对象的构造。delete的原理在空间上执行析构函数,完成对象中资源的清理工作。调用operator delete函数释放对象的空间。new T[N]的原理。原创 2023-07-30 10:00:42 · 129 阅读 · 0 评论 -
类和对象(中)
我们会发现,程序在结束后调用了_t的析构函数,但是Date类并没有析构函数,是因为此时程序结束,需要释放Date类对象,那么也就需要释放Time类对象,但是Date类并没有析构函数,此时系统就会默认生成一个Date类析构函数,然后再其内部调用Time类的析构函数,以此来达到在释放Date类对象同时也释放了Time类对象。,自定义类型就是我们使用class/struct/union等自己定义的类型,看看下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员函数。原创 2023-07-12 10:04:14 · 99 阅读 · 0 评论 -
string类的实现
对于string类来说,我们必须显示来实现拷贝构造函数,否则就会出现深浅拷贝的问题,如果我们显示写拷贝构造函数,系统就会调用默认拷贝构造函数,此时就会发生浅拷贝,浅拷贝就会出现一个问题,s,s1的_str指向了同一块空间,在调用析构函数后这块空间被释放,就会造成野指针的问题。重载>>是为了让string对象像内置类型对象一样可以进行直接进行输入,要注意输入遇见空格就会自动停下来,所以这儿需要使用到get()函数,为了避免刚开始重复的开辟空间,我们可以先开辟一个数组,只需要将数据存此数组,在进行追加就可以。原创 2023-08-04 11:07:01 · 122 阅读 · 0 评论 -
list模拟实现
既然list的指针不满足原生指针的要求,我们此时就可以对list的指针直接进行封装,通过运算符重载,来实现自增,自减,以及解引用等功能,让list可以和vector,string一样,看起来像原生指针一样对进行自增,自减和解引用就是在对数据进行操作。我们就可以发现,Ref和Ptr分别代表引用类型与指针类型,当我们调用const类型迭代器时,编译器就会实例化一个const类型迭代器出来,调用普通类型迭代器时,编译器就会实例化一个普通类型的迭代器。我们为什么要传递三个参数呢?使用 ==运算符与使用!原创 2023-08-15 10:36:15 · 1261 阅读 · 0 评论 -
string类
将字符串对象当前值的子字符串复制到s所指向的数组中。rend:返回一个反向迭代器,指向字符串第一个字符前面的理论元素(被认为是字符串的反向结束)。rbegin:返回一个指向字符串最后一个字符的反向迭代器(即它的反向开头)。此时我们使用getline函数就可以很好的解决这个问题了。begin:返回一个指向字符串末尾后的字符的迭代器。end:返回一个指向字符串末尾后的字符的迭代器。我们平时使用>>操作符是,遇见空格就会停止读取。2.使用范围for进行遍历。1.使用下标进行遍历。原创 2023-08-02 10:10:51 · 115 阅读 · 0 评论 -
类和对象(上)
/ 类体:由成员函数和成员变量组成 };// 一定要注意后面的分号class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。public修饰的成员在类外可以直接被访问。protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)。访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。如果后面没有访问限定符,作用域就到 } 即类结束。原创 2023-07-04 16:41:06 · 84 阅读 · 0 评论 -
(C++)模板初阶
164 //开辟新空间 165 //拷贝数据 166 //释放旧空间 167 T * tmp = new T [ newCapacity ];194 T * _a;197 };220 while(!226 }原创 2023-07-31 09:19:39 · 108 阅读 · 0 评论 -
类和对象(下)
内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。3.尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化,所以建议对类成员变量也使用初始化列表进行初始化。友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。原创 2023-07-27 17:05:35 · 105 阅读 · 0 评论 -
初识C++
return 0;运行程序,我们会发现:这个地方出现了类型重定义的问题,因为rand是包含在头文件中的,我们这是再重新定义一个全局变量rand,就会与已经存在rand存在冲突,那么C++就很好的解决了这个问题。return 0;此时我们就会发现,程序就能很好的运行了,但是打印的结果并不是我们想要的:这儿就不得不提到(::)域作用限定符,我们将在namespace这块空间命名的称为命名空间域,想要访问这块空间里的内容,就需要用到域作用限定符。return 0;原创 2023-07-02 17:11:39 · 115 阅读 · 0 评论 -
C++之unordered_map,unordered_set模拟实现
map/set 底层是使用红黑树实现的,unordered_map/unordered_set底层是用哈希表进行实现的,两者的底层实现是不同的,对于少量的数据,他们的增删查改没有区别,但是对于大量的数据unordered系列是要更胜一筹的,特别是对于查找来说,unordered系列基本可以一直保持高效率;unordered_set属于K模型,unordered_map属于KV模型,但是在底层上我们都是用一个哈希表来实现的,所以我们需要将哈希表的第二个参数设置为T。原创 2023-09-15 22:05:47 · 153 阅读 · 0 评论 -
C++之模拟实现map和set
我们需要注意的是模板中第一个参数K是不可以省略掉的,对于set容器来说第一个参数K和第二个参数K都是一样的,并不会影响什么,对于map容器来说,进行find或者erase时,我们依然需要返回一个key类型的迭代器,所以第一个K不可以省略。对于set容器,我们需要进行键值比较就是对key值进行比较,也就是直接比较T就可以了,但是对于map容器来说,我们需要比较的是键值对<key,value>中的key,我们需要先将key提取出来,在进行比较。=和==就是判断两个迭代器所封装的结点是否是同一个。原创 2023-09-11 19:26:53 · 185 阅读 · 0 评论 -
stack和queue的模拟实现
适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组。原创 2023-08-18 09:11:19 · 882 阅读 · 0 评论 -
反向迭代器
通过前面学习我们就可以知道,反向迭代器的++就是正向迭代器的–,反向迭代器的–就是正向迭代器的++,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可。原创 2023-08-18 15:28:10 · 145 阅读 · 0 评论 -
C++之哈希表、哈希桶的实现
开散列的哈希表插入与闭散列插入思想大致相同,都需要计算哈希地址出哈希地址,但是开散列的哈希表扩容以后,只是将旧表的结点移动到新表当中,并不是复用旧表数据,当开散列的负载因子为1时,我们就创建一个新的哈希表,将旧表结点移动至新表中,在交换旧表与新表数据即可;与闭散列的哈希表不同的是,在实现开散列的哈希表时,我们不用为哈希表中的每个位置设置一个状态字段,因为在开散列的哈希表中,我们将哈希地址相同的元素都放到了同一个哈希桶中,并不需要经过探测寻找所谓的“下一个位置”。原创 2023-09-15 15:33:00 · 400 阅读 · 1 评论 -
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年磨一剑,第二个真正意义上的标准珊珊来迟。原创 2023-09-22 10:47:25 · 100 阅读 · 0 评论 -
C++继承
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。Teacher t;原创 2023-08-20 15:18:53 · 143 阅读 · 0 评论 -
C++11之新的类功能
但是如果我们将拷贝构造,拷贝赋值,析构函数都注释掉,此时Person类就会默认生成移动构造和移动赋值,就会调用他默认生成的移动构造和移动赋值,对于age这种内置类型就完成值拷贝,对于name这种自定义类型因为我们已经实现了他的移动构造和移动赋值,就会去调用他的移动构造和移动赋值。上述代码中,Person类并没有实现移动构造和移动赋值,此时就会调用我们自己实现的拷贝构造函数,会对我们的s1对象的name成员进行深拷贝,也就会调用string类的拷贝构造函数对name成员进行深拷贝。final修饰虚函数。原创 2023-09-26 14:54:31 · 128 阅读 · 0 评论 -
C++之map,set,multimap,multiset的使用
set是按照一定次序存储元素的容器;在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们;在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序;set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代;set在底层是用二叉搜索树(红黑树)实现的。原创 2023-09-02 16:28:06 · 275 阅读 · 0 评论 -
C++多态
多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。必须通过基类的指针或者引用调用虚函数;被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写。在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。原创 2023-08-27 10:32:56 · 154 阅读 · 0 评论 -
C++11之右值引用和移动语义
局部对象的返回问题;插入接口,对象的拷贝问题。而在C++11中引入了右值引用的概念,这两个问题也就得已解决,其实对于浅拷贝的对象,我们只需调用拷贝构造即可,移动构造并没有什么意义,但是对于深拷贝的对象来说,调用移动构造就可以大大提高效率了。原创 2023-09-26 10:06:29 · 101 阅读 · 0 评论 -
C++之模板进阶
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。优点模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生。增强了代码的灵活性。缺陷模板会导致代码膨胀问题,也会导致编译时间变长。出现模板编译错误时,错误信息非常凌乱,不易定位错误。原创 2023-08-19 10:53:38 · 150 阅读 · 0 评论 -
C++11之可变参数模板
下面就是一个基本可变参数的函数模板:其中,Args是一个模板参数包,args是一个函数形参参数包声明一个参数包,这个参数包中可以包含0到任意个模板参数。{}上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特点,也是最大的难点,即如何展开可变模版参数。int main()原创 2023-09-27 10:53:40 · 405 阅读 · 0 评论 -
C++之智能指针
什么是内存泄漏内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。内存泄漏的危害长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。原创 2023-10-15 10:24:00 · 152 阅读 · 0 评论 -
C++之类型转换
而使用dynamic_cast进行向下转型则是安全的,如果父类的指针(或引用)指向的是子类对象那么dynamic_cast会转换成功,但如果父类的指针(或引用)指向的是父类对象那么dynamic_cast会转换失败并返回一个空指针。:隐式类型转换只能是在相近的类型之间进行,比如int与double之间他们的数据类型相似,如果是int与int*就不可以,因为他们一个是指针一个是整形,就需要我们显示的进行转换。dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)原创 2023-10-16 11:22:36 · 115 阅读 · 0 评论 -
特殊类设计
C++98中构造函数私有化,派生类中调不到基类的构造函数,则无法继承,因为子类的构造函数被调用时,必须调用父类的构造函数初始化父类的那一部分成员,但父类的私有成员在子类当中是不可见的,所以在创建子类对象时子类无法调用父类的构造函数对父类的成员进行初始化,因此该类被继承后子类无法创建出对象。但是我们不能将构造函数设置为私有,也不能用=delete的方式将拷贝构造函数删除,因为CreateObj函数当中创建的是局部对象,返回局部对象的过程中势必需要调用拷贝构造函数。单例模式有两种实现方式,分别是。原创 2023-10-16 09:42:21 · 92 阅读 · 0 评论 -
C++之IO流
在C语言中,我们若是想要将一个整型变量的数据转化为字符串格式,有以下两种方法:1、使用itoa函数进行转化。int a = 10;2、使用sprintf函数进行转化。int a = 10;虽然itoa函数和sprintf函数都能完成转化,但是在两个函数在转化时,都需要先给出保存结果的空间,而空间的大小是不太好界定的,除此之外,转化格式不匹配时,可能还会得到错误的结果甚至程序崩溃。在C++中,我们可以使用stringstream类对象来避开此问题。原创 2023-10-17 15:00:58 · 265 阅读 · 0 评论 -
C++之 lambda表达式
实际当我们以[&]或[=]的方式捕获变量时,编译器也不一定会把父作用域中所有的变量捕获进来,编译器可能只会对lambda表达式中用到的变量进行捕获,没有必要把用不到的变量也捕获进来,这个主要看编译器的具体实现。但由于这里是传值捕捉,lambda函数中对a和b的修改不会影响外面的a、b变量,与函数的传值传参是一个道理,因此这种方法无法完成两个数的交换。我们会发现,如果我们需要分别以价格,名字,评价来排序,就需要实现不同的仿函数,这样就显得比较麻烦,因此我们的lambda表达式就登场了。原创 2023-09-28 08:33:50 · 112 阅读 · 0 评论 -
C++之异常
实际使用中很多公司都会自定义自己的异常体系进行规范的异常管理,因为一个项目中如果大家随意抛异常,那么外层的调用者基本就没办法玩了,所以实际中都会定义一套继承的规范体系。这样大家抛出的都是继承的派生类对象,捕获一个基类就可以了。基类可以相当于是一个框架,派生类是具体的异常。然后去具体实现异常的内容,然后抛异常只需要抛派生类,捕捉异常只需要捕捉基类即可。//错误码//错误描述public:{}return msg;原创 2023-09-29 09:05:44 · 109 阅读 · 0 评论 -
C++11之包装器
绑定时第一个参数传入函数指针这个可调用对象,但后续传入的要绑定的参数列表依次是placeholders::_1和placeholders::_2,表示后续调用新生成的可调用对象时,传入的第一个参数传给placeholders::_1,传入的第二个参数传给placeholders::_2。此时绑定后生成的新的可调用对象的传参方式,和原来没有绑定的可调用对象是一样的,所以说这是一个无意义的绑定。它可以接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表,C++中的bind本质是一个函数模板。原创 2023-10-14 09:55:17 · 114 阅读 · 0 评论 -
C++11之线程库
在C++11之前,涉及到多线程问题,都是和平台相关的,比如windows和linux下各有自己的接口,这使得代码的可移植性比较差。C++11中最重要的特性就是对线程进行支持了,使得C++在并行编程时不需要依赖第三方库,而且在原子操作中还引入了原子类的概念。原创 2023-10-12 15:03:15 · 231 阅读 · 0 评论