STL6--模板进阶:非类型参数、模板特化与分离编译机制解析
📌 创作初心:在构建个人知识体系的同时,希望帮助更多正在学习 C++ 模板机制的同学 📚 系列专栏:柯一梦的STL进阶之路 🌐 个人主页:👉 Gitee👉 GitHub 💡 座右铭:功不唐捐,玉汝于成 🎯 本文目标: 理解非类型模板参数的设计意义与使用方式 掌握函数模板与类模板的特化机制(全特化 / 偏特化) 理解 const、引用与指针在模板推导中的作用 搞清模板分离编译的本质原因与解决方案 建立对 STL “header-only 设计”的底层认知 🧠 阅读建议:本文涉及模板底层机制与编译原理,建议先掌握函数模板基础、类模板基础以及 C++ 编译流程(预处理 / 编译 / 链接)模版支持:泛型编程 非类型模版参数模版参数分为类型参数和非类型参数 类型形参:出现在模版的参数列表中,跟在class或者typename的关键字之后的参数类型名称非类型形参:用一个常量作为类(函数)模版的一个参数,在类(函数)模版中,可以将该参数当作常量来使用 我们用静态栈来举一个例子,说明一下我们为什么要学...
STL5--手写priority_queue:从堆到仿函数的完整实现
📌 创作初心:在构建个人知识体系的同时,希望帮助更多正在学习 STL 的同学 📚 系列专栏:柯一梦的STL进阶之路 🌐 个人主页:👉 Gitee👉 GitHub 💡 座右铭:功不唐捐,玉汝于成 🎯 本文目标: 理解 priority_queue 的底层结构(堆) 掌握向上调整 / 向下调整算法 搞懂仿函数在 STL 中的作用 手写实现一个简化版 priority_queue 🧠 阅读建议:本文偏底层实现,建议先掌握 vector 和基础模板知识再阅读 priority_queue的介绍priority_queue的介绍priority_queue是一个具有heap风格的vector,是vector的容器适配器。因为建堆的过程需要很多下标访问,而vector的下标访问效率更极致,所以我们选择使用vector而不是deque。 priority_queue的定义方式priority_queue有三个模版参数:所储存的数据类型,底层容器,建造大堆还是小堆 使用vector作为底层容器,内部构造大堆结构 1priority_q...
STL4--深入理解stack和queue
创作初心:在加深个人对知识系统理解的同时希望可以帮助到更多需要的同学 😄柯一梦的专栏系列 🚀柯一梦的gitee主页 🛠️柯一梦的github主页 座右铭:功不唐捐,玉汝于成 容器适配器我们之前学习了很多的容器,如vector,list,string……但今天我们要学的stack&queue则是两个容器适配器,也就是限制了数据的进出顺序。我们可以打一个比方:容器适配器相当于手机充电器的数据线,将USB的接口变成Type-C的接口,它不存储数据,只是管理了数据的流入流出顺序。==注意==:既然容器适配器规定了数据进出容器的顺序,所以容器适配器就没有迭代器。因为迭代器的作用就是遍历。容器适配器不支持随便访问容器内的数据 stack的实现stack的成员函数: 我们的模拟实现: 123456789101112131415161718192021222324252627282930313233343536373839#pragma once#include<vector>#includ...
STL3--手把手带你实现list
创作初心:在加深个人对知识系统理解的同时希望可以帮助到更多需要的同学😄柯一梦的专栏系列🚀柯一梦的gitee🛠️柯一梦的CSDN主页座右铭:功不唐捐,玉汝于成 list的大体框架,三个类及其主要的成员函数总览结点类的实现要学习list,我们可以从vector入手,vector是一个顺序表,而list只不过就是把每个结点分散开来。如果list要想像vector靠拢,我们只需要保存每一个结点的地址,通过地址来进行节点之间的访问对于节点类的构造: 1234567891011121314template<class T>struct list_node{ T data; list_node<T>* _next; list_node<T>* _prev; list_node(const T& x = T())//这里我们要写带有缺省值的构造函数,因为我们在新开节点的时候,可以直接通过这个传入值 :data(x) ,_next(nullptr) ,_prev(nullptr) { }}; 有些...
STL2--vector的介绍以及使用
创作初心:在加深个人对知识系统理解的同时希望可以帮助到更多需要的同学 😄柯一梦的专栏系列 🚀柯一梦的Gitee主页 🛠️柯一梦主页详情 座右铭:心向深耕,不问阶序;汗沃其根,花自满枝。 目录 1.initializer_list 编辑 2.emplace_back: 3.使用for循环打印多参数的自定义类型对象 3.1迭代器遍历v1 3.2for循环遍历 4.leetcode训练题,写一个杨辉三角 4.1使用C语言 4.2使用C++ 5.迭代器失效 在今天vector的学习之前我们先讲解几个知识: 1.initializer_list我们可以看到 c++11 里面vector的构造函数的一个参数是initializer_list,这个参数的作用是什么呢? initializer_list是一个包装了“ 编译器 临时数组”的轻量级只读对象(这个对象里面有一些成员函数begin,end之类的,并且是用const修饰过了之后的),既然是“ 数组 ”,我们在初始化一些容器的时候就可以用{},传入多个值对容器进行初始化。它的底层原理是:在栈上开辟一个只读的空间,然后vect...
c++入门4--深入解析String类的实现奥秘
创作初心:在加深个人对知识系统理解的同时希望可以帮助到更多需要的同学 😄柯一梦的专栏系列 🚀柯一梦的Gitee主页 🛠️柯一梦主页详情 座右铭:心向深耕,不问阶序;汗沃其根,花自满枝。 今天我们来自主复现一个String类: 1.命名的注意事项因为我们要自己实现一个名叫String的类,可能和库里面的String出现命名冲突,所以我们一般使用命名空间。但是测试文件,函数实现文件在声明、使用函数的时候,只能包含两个域:一个是命名空间域,一个是类域……这未免有些太麻烦了,我们最好在测试文件和函数实现文件中都包含一个命名空间!!!(多个文件可以共用一个命名空间,编译器最后会把他们合在一起)。 注意:我们为什么会命名冲突呢? 我们可以包含string的头文件,并且展开std(因为string类里面的函数实现都在std里),但是我们在自己写string的时候,就会和标准库里面的string混淆。所以就要在多个文件里面使用同一个命名空间把我们自己写的string包起来。我们在命名空间里面使用我们自己写的string的时候,一些东西比如<<,它会先在我们的命名空间里...
C++入门7--string类详解
创作初心:在加深个人对知识系统理解的同时希望可以帮助到更多需要的同学 😄柯一梦的专栏系列 🚀柯一梦的Gitee主页 🛠️柯一梦主页详情 座右铭:心向深耕,不问阶序;汗沃其根,花自满枝。 string既然作为一个类那么我们就不得不提一提它的成员变量和成员函数了 Mumber functions成员函数:constructor(构造函数): string():默认构造函数。 string(const string& str):拷贝构造函数(拷贝构造里面用的是引用传递,引用传递可以省去很多麻烦,比如说开辟空间)。 string(const char*s):用C语言的string来构造c++语言的string。我们来讲一下c语言的string和c++的string有啥区别。c语言的string的本质就是一个字符数组,不能任意修改长度,还存在访问越界的问题;c++的string是一个包含了很多功能的类。 赋值运算符重载operator=: 第一个重载:赋值的对象是一个字符串 第二个重载:赋值的对象是一个c语言的字符数组 第三个重载:赋值的对象是一个字...
C++入门6--模板初阶
1.泛型编程为了引入这个泛型编程,我们先来思考一个问题:如何写出一个通用的交换函数呢,所谓的通用,就是指可以交换整型,浮点型,字符型,以及自 定义 类型呢? 如果我们还没有学C++,那么我们可能Ctrl+C、Ctrl+V去创建很多个函数,但是C++提供了一个很好用的方式,就是给编译器生成一个模子,让编译器根据不同的 类 型来生成不同的函数,即使是自定类型也可以 2.函数模版2.1函数模版的定义函数模版在 使用 时里面的类型被实例化,生成特定类型的函数版本 2.2函数模版的格式 template / template 返回值类型 函数名 (参数列表) { } 2.3函数模版的 原理函数模版就是给编译器提供一个模子,蛋挞本省不是函数,在调用他的时候,会生成具体类型的函数版本。所以就是编译器帮我们做了很多没有用并且重复度的工作。在编译阶段,编译器会根据实参的类型推演生成对应类型的函数。 2.4函数模版的 实例 化使用不同类型的参数调用函数模版时,叫做函数模版的实例化,函数模版的实例化分为显示实例化和隐式实例化。 1.隐式实例化。让编译器根据实参来自动推演模版参数的实际类型...
C++入门5--C++内存管理
1.C/C++的内存分布 【说明】1.栈:主要用于存储非静态的局部变量/函数参数/返回值等,栈是向下生长的。2.堆:堆主要是程序运行时的动态内存分配,堆是向上生长的,堆是向上生长的,但是地址也不一定越来越大,因为如果前面的内存被释放了,就可能被拿来继续使用,这样的话就会变小3.数据段:全局变量或者静态数据4.代码段:可执行的代码/只读常量 例题: 1234567891011121314151617int globalvar = 1;static int Staticglobalvar = 1;int main(){ static int staticvar = 1; int loacalvar = 1; int mun1[10] = { 1,2,3,4 }; char ch1[] = "rxj is so happy"; const int x = 10;//const只是修饰了x的内容,而不是说x就存放在常量区了 const char* ch= "rxj is ...
C++入门4--类的进阶特性
目录:1.再谈构造函数2.Static成员变量及成员函数3.友元4.内部类5.匿名对象6.拷贝对象时编译器的优化 1.再谈构造函数1.1构造函数的构成其实构造函数分为几个部分。1.初始化列表 2.函数体 123456789101112131415161718class rxj{public: rxj() //放置初始化列表的地方 :_age(19)//初始化,就是以一个冒号开始,中间的每个成员都用//逗号分开,并且成员的后面跟上一个括号,用来初始化该成员 ,_height(174) ,_name("rxj") { //函数体的部分 }private: int _age; string _name; int _height;}; 值得注意的是初始化列表的写法,1.以冒号开始 2.每个成员之间用逗号分开 3.成员的后面跟上一个括号,括号里面用于存放你要初始化的值 1.2构造函数的函数体 赋值函数体内赋值,也就是在构造函数的函数体内部{}中对每个变量进行赋值,所谓赋值,就是在这个变量生成以后对其进行...
