![](https://img-blog.csdnimg.cn/2020120410014665.jpeg?x-oss-process=image/resize,m_fixed,h_224,w_224)
C++
文章平均质量分 83
C++学习专栏
飞羚
爱好编程,以技术为乐的程序猿一枚!
展开
-
哈希表初探
文章目录散列函数的构造方法直接定址法除法散列法平方取中法处理散列冲突线性探测二次探测开链 哈希表主要是提供常数时间的基本操作。它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。在哈希表中,散列函数实现地址映射,但是由于存在冲突问题,所以,又必须考虑散列冲突的处理。 散列函数:负责将某一元素映射为“大小可接受之索引”,这样的函数称为散列函数。散列函数的构造方法 如上图所示,散列函数的构造方法较多,下面就几种有代表性的进行总结。直接定址法 直接定址法的散列函数符合如下形式:原创 2021-03-30 14:56:01 · 127 阅读 · 0 评论 -
图
基本介绍相关术语图的实现图的搜索基本介绍 图是由一组顶点和能够将两个顶点相连的边组成的。如下图所示: 根据连接两个顶点边的不同,图可以分为以下两种:无向图:边仅连接顶点,没有方向。有向图:边不仅连接顶点,同时具有方向。相关术语相邻顶点:当两个顶点通过一条边相连时,我们称这两个顶点是相邻的,并且称这条边依附于这两个顶点。度:某个顶点的度就是依附于该顶点的边的个数子图:是一幅图的所有边的子集(包含这些边依附的顶点)组成的图;路径:是由边顺序连接的一系列的顶点组成环:是一条至.原创 2021-02-23 14:08:30 · 71 阅读 · 0 评论 -
lambda函数详解
lambda函数的使用捕获列表常量性区别1常量性区别2lambda函数与仿函数lambda函数的常量性lambda函数与函数指针注意事项lambda函数的使用 lambda函数的完整形式如下:[capture](parameters) mutable->return-type{statement} 其中,[capture]:捕捉列表,捕捉列表可以捕捉上下文中的变量以供lambda函数使用。(parameters):参数列表,与普通函数列表一致,如果不需要传参,那么可以连()一起.原创 2021-01-02 21:53:38 · 8809 阅读 · 0 评论 -
运算符重载探究
意义使用限制非成员函数的运算符重载成员函数还是非成员函数?意义 因为简单的加减乘除符号不能满足我们的需求,例如如果我们要将两个类相加(可能只是针对类中的数据成员相加),常规的加法运算符显然时不能满足需求的;使用operator+( ); //重载加法运算符 需要熟悉一下使用重载运算符的基本用法:class Time{ Time operator+(const Time & t) const;};Time Time:operator+(const Time.原创 2021-01-02 11:57:46 · 123 阅读 · 0 评论 -
C++中IO类的基本解析
文件输入输出缓冲区 上图展示了C++中文件IO设计类的基本关系,从中我们可以看出,标准输入与文件输入类继承于同一个基类,标准输出与文件输出类继承于同一个基类。下面针对C++中IO类的一些特性进行介绍。 c++的输入与输出包括以下三个部分:对系统制定的标准设备的输入和输出,称为标准 I/O(设备);以磁盘文件为对象进行输入和输出,称为文件 I/O(文件);对内存中指定的空间进行输入和输出,称为串 I/O(内存); 其中标准I/O如下:cin :标准输入流,从键盘输入。cout.原创 2020-12-30 22:58:57 · 177 阅读 · 0 评论 -
函数对象简述
使用方式函数与函数对象函数指针与函数对象使用方式 函数对象,简而言之,就是类对于()运算符的重载,使我们可以像使用函数那样使用对象。示例如下:#ifndef TOOBIG_H#define TOOBIG_Htemplate<typename T>class TooBig{public: TooBig(const T &t) : cutoff(t) {} bool operator()(const T &v) {return v > cutof.原创 2020-12-29 13:05:24 · 79 阅读 · 0 评论 -
RTTI简述
RTTI的用途RTTI的使用typeiddynamic_cast与其他转换运算符RTTI的用途 得益于虚函数表,如果派生类实现了基类中的虚函数,通过基类指针或引用可以完成正确的函数调用。 但是也不得不考虑另外一种情况:如果某个派生类中实现了基类定义的虚函数以外的函数,此时,只有基类指针或引用,那么该怎样确认其是正确的派生类类型,从而完成派生类独有函数的调用呢?基于这种情形,因此C++提供了RTTI。RTTI的使用 目前C++支持RTTI元素包括:dynamic_cast和typeid(t.原创 2020-12-28 15:48:41 · 198 阅读 · 0 评论 -
std::function详解
std::function是一个函数包装器模板,最早来自boost库,对应其boost::function函数包装器。在c++11中,将boost::function纳入标准库中。该函数包装器模板能包装任何类型的可调用元素(callable element),例如普通函数和函数对象。包装器对象可以进行拷贝,并且包装器类型仅仅只依赖于其调用特征(call signature),而不依赖于可调用元素自身的类型。 一个std::function类型对象实例可以包装下列这几种可调用元素类型:函数、函数指针原创 2020-12-27 21:22:48 · 2538 阅读 · 0 评论 -
C++内存模型总结
自动存储类型静态存储类型外部链接性内部链接性无链接性动态存储类型 C++主要有三种存储类型:自动存储类型:在函数定义中声明的变量(包括函数参数),他们在函数执行时被创建,在函数执行完毕后被释放。静态存储类型:在函数定义外定义的变量和使用关键字static定义的变量,它们在程序运行的整个过程中都存在。动态存储类型:用new运算符分配的内存将一直存在,知道delete将其释放或程序结束为止。 从存储区域来看,三种类型分布如下: 简而言之:自动存储类型保存在栈,静态存储类型保存在BSS.原创 2020-12-27 17:57:25 · 176 阅读 · 0 评论 -
右值引用详解
##何谓右值 一个最简单判断左值、右值的方式是:等号左边的值即左值,等号右边的值即右值;但为了更加严谨,我们这样定义:能够取地址的,有名字的就是左值;反之,不能取地址,没有名字的就是右值。##右值引用的作用###为什么要有右值引用 我们知道,当类成员中存在指针成员时,使用复制拷贝构造,需要进行深拷贝,但问题在于:我们真的任何时候都需要深拷贝吗?首先来看一下下面的几个代码片段。片段1:String s;String p = s;... 上面无疑是需要深拷贝的,因为无论s,还是p...原创 2020-12-24 22:50:13 · 15421 阅读 · 5 评论 -
虚函数表
虚函数表是实现多态的核心,所谓多态,就是“一个函数,多种实现”,当我们通过类指针或引用调用一个函数接口时,编译器在运行期间将会根据该指针或引用实际指向的对象来调用函数,而这就是通过虚函数表来实现的,换种方式说,虚函数表,完成了动态联编中寻找虚函数哪个执行代码块的任务; 现在来理一下编译器使用虚函数表的过程: 编译器在处理虚函数时,会为基类及相关派生类添加一个隐藏成员,这个成员是用来指向虚函数表的指针,对于每个对象而言,该指针是不同的,该指针指向的虚函数表也是不同的,如果我们把这个指针视作vpr,原创 2020-12-21 21:31:40 · 133 阅读 · 0 评论 -
类的构造、拷贝、赋值、析构函数
构造、拷贝、赋值、析构函数是类的四个特殊成员函数,其特殊之处在于,即使我们没有定义这些函数,编译器也会自动提供默认函数,但如果我们提供了这些函数的显式定义,那么编译器将不会再提供。这可能导致一些隐藏的问题,因此,我们需要对他们的实现进行充分的认识。##默认构造函数 假定有一个类Klunk,那么其默认构造函数定义如下:Klunk::Klunk(){} 编译器为我们提供了一个不接受任何参数,也不执行任何操作的构造函数,我们可以像下面这样调用:Klunk lunk; 但是这种不做任...原创 2020-12-21 19:53:10 · 273 阅读 · 0 评论 -
常见查找、排序算法的实现
查找二分查找排序冒泡排序选择排序快速排序 以下是部分常见排序查找算法的实现,后期会继续补充。查找二分查找static int binarySerach(int *array, int count, int key){ int left = 0; int right = count - 1; while (left <= right) { int mid = (left + right) / 2; if (array[mi.原创 2020-12-17 17:18:43 · 324 阅读 · 0 评论 -
原子操作与原子类型
多线程是并发编程中不可或缺的部分,而所谓原子操作,也就是指多线程中“最小的且不可并行化的”操作,如果一个共享资源的操作时原子操作的话,意味着多个线程访问该资源时,有且仅有一个线程在对这个资源进行操作。通常情况下,原子操作都是通过“互斥”来实现的,例如mutex。这种操作在开发当中使用相当频繁所以我们不做讨论。但是是否还有其他更便于使用的方式呢?c++11给出了答案,就是原子类型。 原子类型,是c++11中提供的一类数据类型,这种数据类型,不需要我们显式使用互斥锁,但是,编译器却可以保证原子类型...原创 2020-12-17 16:46:13 · 421 阅读 · 1 评论 -
c++ interview
鉴于Max Howell的前车之鉴(不熟悉的同学可以搜搜这名大牛的事迹),所以我决定写这篇博客。原创 2020-12-08 16:47:49 · 157 阅读 · 0 评论 -
树综述
一直以来,树这个部分都是我知识结构中的一个漏洞,虽然平时工作中很少用到,但是我觉得还是有必要进行梳理、总结,完善自己的知识图谱。基本概念 树由节点和边组成,边是节点的有序对,一般分布在箭头两端。树的顶端节点,称为树的根。 对于一个边而言,尾部节点是箭头方向节点的祖先,后者是前者的子孙,需要注意:每个节点都是自身的子孙,如果我们要寻找的某个节点的子孙而不包括节点本身时,我们需要指明查找的是节点的特有子孙。 没有子孙的节点成为树叶。 树的节点个数要比边树多1,因为每个节点除了根节点外,都是原创 2020-12-08 15:54:50 · 666 阅读 · 0 评论 -
链表简述
原创 2020-12-06 18:39:24 · 236 阅读 · 0 评论 -
字节对齐详解
字节对齐默认对齐方式指定对齐方式字节对齐主要是针对结构体而言的,通常编译器会自动对其成员变量进行对齐,以提高数据存取的效率;字节对齐有两种方式:默认对齐方式、指定对齐方式;默认对齐方式默认对齐方式内存分配满足以下三个条件:结构体第一个成员的地址和结构体的首地址相同结构体每个成员地址相对于结构体首地址的偏移量(offset)是该成员大小的整数倍,如果不是则编译器会在成员之间添加填充字节(internal adding)。结构体总的大小要是其成员中最大size的整数倍,如果不是编译器会在其末尾添加原创 2020-10-30 15:55:01 · 7900 阅读 · 0 评论 -
vector要点
vector的插入移除 vector是一个有序群集,支持随机存取,可以根据索引获取元素;在末端附加活删除元素时,vector的性能相当好,但是如果要在前端、中部安插或者删除元素,那么操作点之后的没一个元素都要移到另一个位置,将会导致效率低下;大小与容量 vector采用内存动态分配机制,当vector中元素达到临界值时,vector会自动重新配置;vector中元素个数可以使用size(), 容量是capacity(),超过容量,vector就会重新配置; 需要注意的是,重新配置会导致以下结果原创 2020-11-16 22:54:55 · 483 阅读 · 0 评论 -
list要点
List特点 list本质是一个双向链表,和vector存在明显区别:不支持随机存取,也就是说不支持索引获取,如果要获取某个元素,必须遍历到该元素,因此list没有[]重载,也没有at()函数;任何位置安插删除元素都很快,始终在常数时间内完成,因为不需要移动任何元素,只需要修改其前向及后向指针指向即可;元素存取 由于List不支持随机存取,因此不能通过[]、at()获取元素,只有front()及back()函数能够直接存取元素,这里需要注意,这两个函数返回的并非迭代器;迭代器我们需要使用b原创 2020-11-17 15:15:12 · 102 阅读 · 0 评论 -
map要点
map分为map和multimap,前者元素不允许重复,后者则允许元素重复,这种重复包括key值重复甚至整个元素重复; map的是定义在std内的class templates:template <class Key,class T,class Compare = less<key>,class Allocator = allocator<pair<cosnt key,T>>> class map; 其中:第一个参数为key第二个参数为原创 2020-11-17 23:56:53 · 658 阅读 · 0 评论 -
set要点
set和map十分类似,唯一不同的可能在于map是关联式容器;set分为set和multisets,前者元素不能重复,后者允许;set通常是以平衡二叉树完成的;set特点 由于二叉树搜索元素时的良好性能,其搜索函数算法具有对数复杂度,这比STL提供的线性搜寻要快很多; 和map一样,由于自动排序,我们不能直接改变元素值,而必须先删除旧元素,再插入新元素,为了支持这种行为,所以set不提供用来直接存取元素的任何操作函数,而必须通过迭代器间接存取,即使时迭代器获取的元素,也是常数;安插移除原创 2020-11-19 11:41:45 · 140 阅读 · 0 评论 -
Satck与Queue要点
Stack定义 stack的特点是先进先出,与queue正好相反; class stack定义如下:nemespace std{template <class T, class Container = deque<T> >class stack;} 第一个代表元素型别,第二个参数用来定义stack内部存放元素所用的实际容器,默认是使用deque;从定义我们可以看出,stack只是很单纯地把各项操作转化为内部容器的对应调用,我们可原创 2020-11-23 12:01:13 · 141 阅读 · 0 评论 -
Deque要点
deque即双端队列,似乎并不常用,但是stack、queue都是默认使用deque实现的,所以还是有必要学习一下deque,了解其基本实现,这样对于stack、queue,也能有更深入的理解;deque特点 deque和vector非常相似,它也使用动态数组来管理元素,接口也和vector相差无几,不同的是,deque首尾都开放,因此能在两端进行快速安插与删除; deque使用动态扩展,那么是怎样实现的呢?deque通常作为一组独立区块,第一区向某方向扩展,最后一个区块朝另一个方向扩展,如下原创 2020-11-24 11:04:03 · 176 阅读 · 0 评论 -
STL中常用算法总结
STL算法众多,很难一一概括,对于我们日常软件开发而言,其实也不需要全部掌握,我们只需要掌握其中最常用的算法并能熟练使用即可。查找算法count:利用等于操作符,把标志范围内的元素与输入值比较,返回相等元素个数;count_if:利用输入操作赋,对标志范围内的元素进行操作,返回结果为true的个数;equal_range:功能类似equal,返回一对iterator,第一个表示lower_bound,第二个表示upper_bound;find:利用底层元素的等于操作赋,对指定范围内的元素与输原创 2020-11-24 21:51:39 · 371 阅读 · 0 评论 -
c++11新特性一窥
__VA_ARGS_noexceptfinal/override控制右值引用auto类型推导decltype基于范围的for循环强类型枚举智能指针常量表达式变长模板原子类型与原子操作指针为空lambda函数 c++11在c++标准中大名鼎鼎,虽然已经出了c++17、c++20,但是c++11仍然是知名度最高的,所以有必要系统学习一下c++11,以下所有内容均基于《c++11新特性的理解》这本书进行总结。_VA_ARGSnoexceptfinal/override控制右值引用auto类型推导.原创 2020-11-26 17:16:46 · 229 阅读 · 0 评论 -
智能指针总结
智能指针用于管理动态内存,当智能指针过期时,这些内存将自动释放;智能指针也是模板,当我们创建智能指针时,需要提供其所指向的类型; 可以从 auto_ptr 的构造函数来了解一下智能指针的基本构成:template<class X> class atuo_ptr{ public: explicit auto_ptr(X* p=0) throw;} 从上面可以看出,智能指针中保存了一个指针成员,在构造函数中传入赋值;目前 auto_ptr 已经被弃用,主要原因在于:原创 2020-12-01 10:38:25 · 139 阅读 · 0 评论 -
函数模板初探
函数模板是一个相当大的群体,很难以一篇文章的形式将其彻底总结完,本节将总结一些函数模板的基本使用,至于更加高级的用法,可能在后面加以深入;函数模板的基本使用 如果一个函数,针对各种数据类型,如果其实现算法都大体相同,那么就可以使用函数模板; 其实从上面的使用场景可以看出,似乎我们也可以通过函数重载实现,但问题在于,如果有相当多的数据类型,那么可能要定义同样多类型的函数重载,这将会成为一项复杂的工程; 因此,当我们考虑使用函数模板时,如果涉及的类型较少,那么可以直接使用函数重载; 同样,原创 2020-12-03 22:59:11 · 68 阅读 · 0 评论 -
bind详解
bind与占位符绑定普通函数绑定成员函数绑定函数对象 如果你还在使用bind1st/bind2nd,那么恐怕已经out了,Boost提供了更强大的武器bind,用于函数对象的绑定; bind接受的第一个参数必须是可调用对象f,包括函数、函数指针、函数对象、成员函数,之后最多可以接受9个参数,参数的数量必须与f的参数数量相等,这些参数姜维作为f函数的参数。 bind会返回一个函数对象,它内部保存了f的拷贝,当发生调用时,之前参数将传给f函数完成调用。bind与占位符 bind与占位符可以.原创 2020-12-02 22:58:29 · 7228 阅读 · 0 评论 -
设计模式综述
设计模式六大原则设计模式构建型模式工厂模式单例模式建造型模式原型模式结构型模式适配器模式桥接模式组合模式装饰模式外观模式享元模式代理模式设计模式对于软件设计的重要性不言而喻,每一个c++程序员都应该学习,但是设计模式又不是那种死记硬背的知识,更多的是需要我们能够在软件开发中磨炼;如果说设计模式中23种设计模式是术,那么六项基本原则就是道,术固然重要,但是更重要的是我们要从术中领悟道的存在,一旦领悟,设计模式将不止23种;六大原则开放封闭原则:对修改封闭,对扩展开放;例如使用抽象类派生扩展功能;单一原创 2020-11-03 11:41:17 · 315 阅读 · 0 评论