- 博客(24)
- 收藏
- 关注
原创 C++模板元编程系列-2.类型转换与奇异的递归模板模式
从本节开始正式介绍模板相关的高级设计和语法,要注意的是奇异的递归模板模式与混入都和继承有很强的联系。 我们都知道,在继承中派生类可以调用到基类的public成员和protected成员,但是在常规继承中,基类是不可能反过来调用到派生类中的任何派生类特有的成员的,但是在使用了奇异的递归模板模式的继承后,在基类中就可以调用到派生类特有的成员了,先来看看具体代码长什么样子:运行结果如下: 上方代码的细节非常多,首先在标准继承的视角中,上方的继承体系是public继承,并且只有非虚函数,那么对于在函数
2026-06-17 08:00:52
32
原创 AI底层系列:用C++实现线性代数的公式推导与算法设计-6.线性方程组的解集
对于线性方程组的解集我们已经并不陌生了,无非就是唯一解,无数解和无解三种情况,在本节将会从另一个角度来看待线性方程组的解集。 考虑下方两个线性方程组:{x1+x2+x3=103x1+2x2+x3=9x1+x2=7\begin{cases}x_1 + x_2 + x_3 = 10\\3x_1 + 2x_2 +x_3 = 9\\x_1 + x_2 = 7\end{cases}⎩⎨⎧x1+x2+x3=103x1+2x2+x3=9x1+x2=7{x1+x2+x3=03x1+
2026-06-16 20:59:58
139
原创 AI底层系列:用C++实现线性代数的公式推导与算法设计-基础篇-5.矩阵方程
在前四节中,我们学习了两种表示线性方程组的方法, 即线性方程组和向量方程,在本节将给出线性方程组的第三种表示方法:矩阵方程,并使用C++实现相应的表示。 考虑下方的向量方程:x1[232]+x2[435]+x3[452]+x4[512]=[744]x_1\begin{bmatrix} 2 \\ 3 \\ 2\end{bmatrix}+x_2 \begin{bmatrix}4\\ 3 \\ 5 \end{bmatrix} + x_3\begin{bmatrix} 4 \\ 5 \\ 2\end{bma
2026-06-13 16:29:37
568
原创 Linux操作系统系列.动态加载
在上一章,我们已经知道了ELF文件的生成过程和虚拟地址的本质,但是我们的程序还在磁盘上躺着,仅仅只是初始化出了VMA,程序还没有真正的运行起来,在本章,正式开始讲解如何加载磁盘数据到物理内存中。
2026-06-13 13:50:23
182
原创 Minetest游戏引擎源代码解析
先来为没有听说过Minetest(现已更名为Luanti)的读者简单介绍一下,Minetest是一款类似于我的世界类型的沙盒类游戏的游戏引擎,100%开源,是初学者学习游戏引擎设计与实现的最佳实践,读者如果想要下载源代码的话可以在Linux(Ubuntu)的终端输入如下命令:更详细的介绍可以去问AI或是查看官方文档,这里不多BB,直接开始上干货。
2026-06-12 15:02:25
279
原创 C++模板元编程系列-1.继承
随着对于编程的不断深入,笔者越发体会到自己的编程知识缺了一部分,那就是模板,对于模板的基础知识笔者是大概掌握的,比如函数模板,类模板,特化等基础知识,但是更进一步的类型萃取,模板元编程,混入等高阶模板的语法是完全无法理解的,因此在学习的途中写下这一系列的博客,要说明的是,本系列不会介绍模板的基础知识,最终的目标是掌握模板元编程这一高级编程技术。(注:笔者学习使用到的书籍有《C++新经典:模板与泛型编程》和《Effective C++》第三版》
2026-06-10 07:38:04
143
原创 AI底层系列:用C++实现线性代数的公式推导与算法设计-基础篇-4.向量与向量方程
在上三节中我们学习了线性方程组,解线性方程组,行阶梯型矩阵,行化简矩阵,主元等线性代数相关的知识并使用C++实现了相应的函数,在本小节将学习线性代数中的一个重要概念:向量。 从最简单的代数视角来看,向量本质上就是有序的一组数,在各个维度中都存在向量,其标准的定义是既有大小,又有方向的量,下面让我们从最简单的零维开始,逐步扩充到n维。 零维只存在一个点,没有方向的概念,那么自然也就不存在有向线段,因此在零维中只存在唯一的一个零维向量,使用数学符号{0}\{\mathbf{0}\}{0}表示,从几何上来
2026-06-07 17:17:28
172
原创 AI底层系列:用C++实现线性代数的公式推导与算法设计-基础篇3.主元与解情况的判断方法
在本节将给出答案并使用C++实现相应的判断解情况的函数。
2026-06-03 20:49:32
236
原创 AI底层系列:用C++实现线性代数的公式推导与算法设计-基础篇2.行阶梯矩阵与行化简矩阵
本文系统介绍了行阶梯型矩阵与行化简矩阵的概念及其在线性方程组求解中的应用。首先通过具体案例分析了线性方程组解的三种情况(唯一解、无穷解、无解),并从代数与几何角度进行解释。重点阐述了行阶梯型矩阵的判定标准(非零行在零行上方、先导元素位置关系等)及其化简为行化简矩阵的附加条件。文中指出,任何非零矩阵均可化为行阶梯型,但只有唯一对应的行化简矩阵,这一性质为判断线性方程组解的情况提供了有效工具。最后还讨论了矩阵化简唯一性的直观理解。
2026-05-31 21:06:44
383
原创 问题链式学习策略-1.智能指针与右值引用
答: 右值一般是指临时变量或常量,生命周期只在当前一行,没有名字,用完就会立刻被销毁。左值一般是指局部变量或全局变量这些生命周期较长,有名字,会跨行持续的使用的变量。将亡值是指在编程中使用std::move(左值)给左值打上了资源可移动标签的值,可以认为将亡值是右值与左值的中间状态,将亡值也属于一种右值。
2026-05-30 09:16:49
201
原创 AI底层系列:用C++实现线性代数的公式推导与算法设计-基础篇-1.线性方程组
你可能不是很了解线性代数,但是你一定了解现在市面上各种各样的AI,AI的强大之处相信就不用笔者多说了,笔者在此处要说明的是无论是何种类型的AI,何种类型的主流AI算法,何种类型的大模型,又或者是那些听起来就非常牛逼的名词,比如:Agent算法,LLM算法,大模型算法,多模态,卷积神经网络....这些最前沿的AI相关知识,其最最最底层的就是线性代数,微积分与数理统计这三个模块,其中又以线性代数最为重要,线性代数可以说是AI的神经元,是AI最为核心的部分。
2026-05-29 21:40:33
233
原创 面试题设计与回答系列: 1.智能指针
笔者近期准备要去面试了,笔者并没有面试的经历,但是笔者也不喜欢直接去看面经,因此笔者采取了假设自己是面试官,来自己设计问题与回答,笔者称该学习策略是"问题链式学习",无意间摸索出来的,效果非常不错,适合大范围的扫盲与串联知识点,在此展示具体的流程,希望能够给读者一些帮助。
2026-05-29 08:03:54
362
原创 Linux内存管理:虚拟地址空间(静态分析总篇)
由一个进程的虚拟(或逻辑)地址所构成的地址空间,一看就非常抽象,说了跟没说一样,现在让我们先抛弃抽象的概念,从一个故事开始:现在有一个千万富翁,他手里面有3千万,这个富翁有5个儿子,富翁对他的每一个儿子都说:儿啊,等我死后,我的三千万就都是你的了。此时他的每一个儿子都很开心,他们都认为等老爹死了就可以得到他的三千万,然后他们就开始幻想了,大儿子想等拿到钱后就买一百双AJ,二儿子想等拿到线后就去澳门当赌神.....但是此时钱还不是他们的,他们就只是在做白日梦而已。
2026-05-24 09:09:38
448
原创 Linux内存管理系列:3.页表的实现细节
这个认识是没错的,是对页表的一个功能性和概念性认识,读者在阅读下方的页表具体技术细节时也应该要时刻明确页表的作用本质上就是哈希映射。但是这个认识太浅了,页表作为虚拟地址空间中一个重要的模块,其实是一个非常复杂的东西,涉及到了权限,操作系统管理内存的方式和单个虚拟地址的划分等知识,下面就来进行讲解(先进行原理的说明,再分析源代码的具体实现)。
2026-05-09 11:01:35
410
原创 Linux内存管理系列:4.伙伴系统
伙伴系统在上篇文章对_count的字段分析时提出来过,具体来说所有的页框可以分为两类,一类是没有被使用和引用的(_count = -1),这部分页框就是空闲的;一类是被使用或引用的,这部分页框就是非空闲的,而伙伴系统就是管理空闲页框的,其主要任务就是。
2026-05-09 11:01:18
514
原创 Linux内存管理系列:2.虚拟地址空间的实现细节
从本篇文章开始将讲解虚拟地址空间的实现的具体技术细节,会涉及到一部分的Linux源代码分析,可能会比较枯燥,希望读者保持耐心,在此处还要进行说明的是:虚拟地址空间机制贯穿了整个操作系统中的几乎所有概念,因此本章会涉及到比较多的操作系统概念,比如进程,线程,文件系统,MMU....,所以本章并不建议没有系统的学习过操作系统的读者阅读,又或者是可以只挑自己可以理解的部分进行阅读。
2026-05-08 16:16:20
361
原创 Linux内存管理系列:1.初探虚拟地址空间
如果你了解过操作系统,那么虚拟地址空间一定会是一个让你非常迷惑的点,作为一个抽象的概念,虚拟地址空间在操作系统中有着无与伦比的地位,想要学明白操作系统管理内存的方法,理解虚拟地址空间就是必须的。而虚拟地址的抽象性就意味着其必然是非常难理解的,比如现在提出一个问题:现在一款大型游戏动辄就是几百G,但是电脑的内存条撑死了就只有十多G,十多G的内存是怎么运行起几百G的游戏的呢(后面的文章将会回答该问题)?
2026-05-08 15:54:29
371
原创 计算机中的机械设备:磁盘
本章先来简单的介绍一下磁盘,让读者看看磁盘内部是什么样子的,把抽象的名称变为具体的实物。利用磁记录技术来存储数据的存储器。由于磁盘是使用机械结构,这既有优势,又有缺点,其优势是:磁盘的价格比较低,并且存储空间非常大。其缺点是磁盘比较笨重,IO(输入输出)效率比较低并且可能会由于机械原因造成磁盘数据丢失(下文详细说明)。下面来看看磁盘具体是什么样子的:从上方的图片也明显可以看出,磁盘内部确实是使用机械结构实现的,其机械结构的具体组成在下文会进行详细的介绍。
2026-03-18 23:28:25
442
原创 C语言的指针
在编程中,指针与地址是同一个概念,因此可以先从地址的角度理解指针。编程中的地址可以说是对实际生活中地址的抽象,比如在收发快递时,快递员通过提供的地址,就可以准确的定位到你家的位置。对应到编程中,可以说操作系统对每字节的内存空间都进行了编号,通过这个编号,就可以准确定位到每字节的内存空间,这个编号,就是所谓的指针,并且我们在大多数情况下并不关注指针本身,而是关注通过这个指针能够找到的资源数据。然后很自然的会产生一个问题:操作系统是怎么产生这些编号的?
2026-01-26 22:29:47
1428
原创 函数的缺省参数与函数的重载
缺省参数是一个非常简单的语法:即在声明或定义函数时为函数的参数指定⼀个缺省值。在调用该函数时,如果没有指定实参就采用该形参的缺省值,否则使用指定的实参。int c = a;int d = b;如上方的代码,函数fun的a=10与b=20就是形参a与b的缺省值,在调用处,k没有传入实参,因此直接使用缺省值,k最终的结果是30,在r处,传入了实参1和2,此时以传入的实参为准,因此r最终的结果是3。
2026-01-13 21:32:26
626
原创 C和C++的内存管理
要重点注意的是realloc函数,其本身用于扩大已经开辟的内存的空间,但是在扩容的过程中可能会出现两中情况,情况1:扩容后没有覆盖掉后方的有效数据,此时就可以直接进行扩容(原地扩容),情况2:扩容后覆盖掉了后方的有效数据,此时会先在内存空间中找到一片足够大的空间,再将原本的数据拷贝过去,并释放掉原本空间处的内存,在新的空间中完成扩容。原因就是new的底层实际上是对malloc的封装,并且内置类型也不需要调用构造函数,因此可以使用free进行内存的释放,但是,这是一种非常丑陋的写法,非常不推荐这样写。
2026-01-04 19:12:58
751
原创 C++编译器的默默付出
先来聊些题外话,就如上文所述,C++是一门效率非常高的语言,这其中编译器的优化只是一部分原因,另一个原因就是:C++的程序可以直接跑在操作系统之上(相当于没有中间商),拿Java进行对比,Java的程序不是直接跑在操作系统之上,而是先在操作系统之上搭建一个虚拟机,再让程序跑在虚拟机之上(相当于有了一个中间商)。
2026-01-02 21:02:21
904
原创 C++的命名空间
如上方代码,变量b指定查找了作用域T中的a,因此b被赋值为20,而c没有指定作用域,遵循先在局部找,再去全局找的规则,因此c被赋值为10,要注意的是变量d,其同样没有用::指定作用域,但是在局部和全局中都找不到变量e,此时是不会去命名空间T中查找的,因此在d处的赋值会报错,对于变量g,其指定要去T中查找,但是T中并没有变量f,此时编译器是不会再去全局找到f给g赋值的,因此g的赋值也是错误的。但是在2代码处,在指定了作用域后,main中给变量a的赋值又是可以的。(在大型项目中,非常不推荐使用这种方法)
2026-01-01 19:46:00
642
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅