- 博客(23)
- 收藏
- 关注
原创 解剖C++模板(2) —— 模板匹配规则及特化
众所周知,模板声明部分的尖括号中的内容是声明模板形参,而调用模板时的尖括号是给模板传参。然而这样理解仅仅停留于现象,只是将模板形参传参和函数传参的过程划等号了。C++ 的函数重载匹配并非真的进行匹配,因为函数名修饰规则导致重载总能第一时间找到匹配的函数。而模板不同,对模板传参进行实例化过程中,模板匹配的过程是真实发生的。
2024-11-12 21:09:41 495 7
原创 解剖C++模板(1) —— 模板中的关键字及符号
先说在前头,模板的初衷是泛型,但它不是固定格式,每一个关键字以及符号都有其规则。这应该算是模板入门的经典模板头部了。不接触模板元编程的 C++ 用户也很容易将它当作固定格式(像极了初学者觉得 cpp 文件开头一定要书写 using namespace std;),以至于在创建复杂模板或者多个模板配合使用时像无头苍蝇般写到哪儿算到哪儿,于是出现各种不明原因的错误。这个系列目的在于说明这些规则,让 C++ 用户在写模板的时候知道自己在干嘛。
2024-11-12 02:08:36 1100 5
原创 C++20 概念与约束(3)—— 约束的进阶用法
上一篇文章中提到过约束可以无限嵌套。末尾也提到不考虑嵌套约束的情况下,模板因为 SFINAE 规则的存在,其中 requires 子句只要存在返回值,只有可能是 true 这一种结果。在非模板中,如果 requires 子句中的表达式非法是直接报错。那如果 requires 子句中的表达式是合法的但是不符合要求呢?如下图所示。接下来再讨论嵌套约束的情况。不同于布尔值的 true false ,requires 主句对后续表达式的处理后将得到符合要求与不符合要求两种结果。
2024-11-10 16:20:01 1480 19
原创 C++20 概念与约束(2)—— 初识概念与约束
C++20 中引入新的编译期关键字 concept 用于创建概念。个人认为将其翻译为“构思”更为贴切。直接使用时,它更像一个只能用于模板的布尔类型关键字。而如果用于模板中,他会将模板类型先带入自身,当自身条件为 true 才会实例化模板,否则该模板被弃置。因此该关键字几乎全用于 SFINAE 规则。如上图, foo 将因为找不到匹配模板而报错。因此只需要通过逻辑条件运算符将多条语句进行列举即可。
2024-11-09 22:03:32 1257 23
原创 C++20 概念与约束(1)—— SFINAE
众所周知,C++在使用模板时,如果有多个模板匹配,则编译器会选择最匹配的一个模板进行实例化,这也正是模板特化和偏特化的依据。根据上面这张图中的现象,列举下面几个示例:1、不存在模板的情况下, foo(1.0) 中的 1.0 将进行隐式转换。2、若存在模板,模板匹配的优先级高于隐式转换。3、若不存在实例, 编译器将用最合适的模板(图中的特化版本)进行实例化。4、当然,在不存在实例也不存在匹配模板的情况下,编译器才会报错。从上述现象可知,优先级中,模板实例化 > 隐式类型转换 > 报错。
2024-11-09 13:24:17 1607 56
原创 初级数据结构(七)——二叉树
链表形式的二叉树在逻辑上相对于顺序表尤其复杂,当然也比顺序表更为灵活。链表形式的二叉树任何操作,本质都是有条件地遍历各个节点。而熟练掌握递归算法对遍历链表形式二叉树尤为重要。二叉树有三种常用遍历顺序,称为前序、中序和后序。前中后序指的是访问节点中数据的次序。除此之外还有层序遍历。本文主要围绕这四种遍历方式展开讲解。可以说弄清楚这四种遍历方式,并在需要时选择其中最佳遍历方式,二叉树也就可以随意把玩了。
2023-12-22 18:16:49 5029 51
原创 轻松搞懂递归算法
函数内部调用自己的函数称为递归函数,这点大家应该早有了解。那什么是递归?递归这个词需要拆分成递和归来理解。递是传参,归则是返回,一切函数在调用时必然经过这两个步骤。在递归函数中,由于调用自身的属性,传参过程和返回过程都是连续的。
2023-12-20 02:37:48 1212 23
原创 初级数据结构(六)——堆
堆结构属于完全二叉树的范畴,除了满足完全二叉树的限制之外,还满足所有父节点数据的值均大于(或小于)子节点。父节点大于子节点的堆称为大堆或大根堆,反之则称为小堆或小根堆。
2023-12-17 21:41:40 2275 30
原创 初级数据结构(五)——树和二叉树的概念
自然界中的树由根部开始向上生长,随机长出分支,分支之上又可长出分支,层层递进,直至长出叶子则此分支结束。数据结构中“树”的概念便是借鉴大自然中的树,将下图垂直镜像翻转便是如此,只是在画结构图时往往更习惯由上向下画。它从根节点开始不断长出分支,直至终端。与自然中的树不同点在于,随着数据后续插入,树结构的叶子节点也可能变为分支节点。
2023-12-16 19:43:53 3675 30
原创 深入理解C语言的函数参数
为什么定义了两个参数的函数在调用时传入多个参数,编译器既没报错,对输出结果也没有丝毫影响?为什么明明函数创建时只设定了一个参数,传入六个参数全部能在函数内部打印出来?printf和scanf的任意参数个数又是怎么实现的?
2023-12-14 19:44:22 1564 25
原创 初级数据结构(四)——队列
栈结构特性为LIFO ,队列则是与之相反的先入先出,后入后出,也称为 FIFO ( Fist In Fist Out )。队列与栈的区别只在于弹出顺序,其余完全一致。但是,基于队列的特性,如果选用顺序表实现,则需要不断腾挪数据以填充弹出的头部位置,因此这里最好选用链表来实现以减小计算机资源的开销。
2023-12-13 19:09:37 1427 36
原创 初级数据结构(三)——栈
基于某些需求(如通过程序判断记录数学公式字符串的大中小括号是否配对、计算字符串中的数学公式的值、甚至最基本的数组倒序等),程序的数据处理需要用到后入先出的特性,对这类数据进行操作的结构就称为栈结构。
2023-12-13 17:48:07 1380 17
原创 初级数据结构(二)——链表
顺序表的劣势在于,开辟空间并非随需开辟,释放空间也显得不那么灵活。如果顺序表做到每次增加数据便拓展空间,删除数据便回收空间,基于 realloc 可能异地开辟的特点,搬运数据的时间复杂度为 O(N) 。如果顺序表的长度是几千万乃至几亿,每添加或者删除一个数据,其延迟是难以忽略的。如果有一种储存方式可以解决上述问题,做到每一个数据的空间都按需开辟,且按需释放,那么在最极端的情况下,它甚至可以节省近一半存储空间。
2023-12-07 04:39:47 2150 35
原创 初级数据结构(一)——顺序表
现实中数据记录一般都记录在表格中,如进货单、菜单等,它们的最大特点就是有序。表述中可以用第一项、第二项、第 n 项来描述表格中某个数据或者某串数据。在 C 语言中,数组的特点恰好匹配此功能。由于数组在内存中的储存方式就如同列表依序排布,对数组可以用 arr[n] 或者 *(arr+n) 来迅速获得第 n-1 项数据。再加上而且数组是 C 语言的原生类型,创建数组极其便利,作为有序数据的载体着实是不二之选。
2023-12-05 20:48:50 3496 39
原创 徒手凹一个成语接龙——字符串拓展(未完成)
成语接龙玩法的规则无需过多解释,大致流程如下:由于成语接龙的规则是同音接龙即可,因此上图中的 abcdefgh 必须转化为拼音的形式再进行比对。网上有很多现成的库可以直接调用,但这里,我们选择徒手凹一个。
2023-11-28 00:01:13 1193 11
原创 C语言指针类型与数组的深入探讨
数据在内存中存放必须开拓对应空间,每个数据所占空间都有一个或若干个连续的地址。内存空间地址最小以字节为单位递增,常以 16 进制无符号整型表示。32 位系统内存空间地址为 0x00000000 ~ 0xFFFFFFFF;64 位系统内存空间地址为 0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF。获取数据的地址用取地址符号 —— &。
2023-11-22 03:44:17 2227 16
原创 扫雷(实现用鼠标操作控制台)
要实现棋盘类游戏,自然而然能想到的必然是二维数组。通过定义一个数组 arr ,并经由数组元素 arr[y][x] 来记录棋盘上坐标 (x, y) 的内容。扫雷也是如此。该数组记录的信息只有雷区和安全区两种。之所以定义为 12 * 12 的数组是为了方便后续判断。游戏过程中,如果翻开的是雷区直接结束游戏,若不是雷区则显示周围 8 个格子中的地雷数量。根据以上规则,先制定数组元素中存放什么内容。首先每个格子周围只可能存在 0 ~ 8 个雷,所以元素中以 0 ~ 8 存放周围地雷的数据,存放 -1 表示地雷。
2023-11-03 00:47:13 729 18
原创 C语言中数据的写入、存储及读取
C语言众多数据类型归根结底,存储的格式只有整型及浮点型,一切其他数据类型都是在此基础上进行拓展。如字符型本质是一个 1 字节的整型,字符串是由若干个字符型元素构成的数组,至于指针类型是 4 字节(32 位)或 8 字节(64 位)的整型。
2023-10-28 22:33:24 2002 4
原创 浅谈病得不轻的循环语句用法
众所周知,C语言中循环的三种结构:for、while、do...while。这样中规中矩的语句结构在此也没啥好多赘述了。正如标题所说,咱目的是让人看完代码后脸色一沉,断言此人病得不轻。
2023-10-23 18:16:59 412 6
原创 一个关于“1到100中所有整数共出现多少次数字9”的突发奇想
当 i 是1~9 时,i / 10 %10 = 0,因此,count 错误地加 1 ,当 i 是 10~99 时,i / 100 % 10 = 0,count 又错误地加 1。观察上述代码,其中 count += i % 10 == 0 可以写作 count += i / 1 % 10 == 0 ,即是说,i 的除数以10倍递增,类似位移操作符。正如算法所构思的,只判断了个位和十位,而判断十位的方法仅仅是通过除以 10 实现的。但这样,若判断数取 0 ,循环到 i = 0 时,仍旧会少统计一个 0。
2023-10-16 05:33:58 588 7
原创 C语言入门代码常用名词
一个完整的c语言程序只包含完整的 main 即可,但没有任何功能。而通常的c语言程序最外层往往包含:1、头文件2、#define 符号常量3、main函数4、全局变量5、其他函数。
2023-10-14 02:50:00 781 3
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人