自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(38)
  • 收藏
  • 关注

原创 深入理解 C++ auto:从推导规则到最佳实践

auto不是 “偷懒工具”,而是现代 C++ 提升开发效率、降低维护成本的重要特性。它的规则并不复杂,核心就是一套推导逻辑 + 几个修饰符组合。

2026-06-17 21:56:16 401

原创 constexpr函数

当传入编译期常量作为参数时,可在编译阶段计算出结果,其返回值可作为常量表达式使用(如数组长度、模板非类型参数、枚举初始化等);当传入运行期变量时,也可作为普通函数在运行时执行。属性,可以直接定义在头文件中,被多个翻译单元包含也不会出现「多重定义」链接错误,彻底解决了 C++11/14 中头文件 constexpr 变量的链接问题。” 的极简编译期函数,逐步演进到 C++20/23 接近通用的编译期计算体系。能力的质变版本,打破了绝大多数核心限制,编译期计算能力接近运行时,同时新增两个互补关键字完善语义。

2026-06-16 21:33:04 367

原创 const和constexpr常量表达式

值不会发生改变编译阶段就能计算出确定结果简单来说:编译器在翻译代码时,就能 100% 确定它的最终值,不需要等待程序运行时计算。常量表达式是属性:描述一个值能否在编译期确定const是语法约束:表示「运行时不可修改」,一部分const变量具备常量表达式属性constexpr是强制标记:强制变量必须是常量表达式,由编译器做编译期检查理解了常量表达式的本质,你就能避开 C++ 里绝大多数和 const、编译期常量相关的坑,写出更安全、性能更好的代码。

2026-06-16 20:55:45 357

原创 C++ IO 流 底层原理与常用函数全解(面试硬核版)

C++ IO 流的本质是 **"字节序列的抽象"**,它将不同的输入输出设备(文件、控制台、网络、内存)统一抽象成 "流" 对象。无论底层设备是什么,上层都使用相同的接口进行读写。C++ IO 流允许你自定义streambuf对象,实现自己的缓冲区逻辑。这是 IO 流最强大的特性之一。C++ IO 流的底层核心是缓冲区机制和面向对象抽象。理解了三层缓冲区架构,你就能解释所有 IO 流的奇怪行为。掌握了本文介绍的所有常用函数,你就能写出高效、稳定、无坑的 IO 代码。缓冲区机制和刷新时机。

2026-05-28 13:44:05 415

原创 ++ 后端面试核心:Lambda / 仿函数 /function/bind 深度解析

在 C++11 之后,可调用对象体系彻底重构了 C++ 的编程范式。Lambda、仿函数、std::bindSTL 算法(sortfor_eachfind_if)的基础回调函数、事件驱动、异步编程的核心设计模式(策略、观察者、命令)的现代实现方式面试官考察你是否真正理解 C++ 类型系统和编译期机制的试金石重载了operator()运算符的类,其对象可以像函数一样被调用,因此也叫函数对象。是 C++11 引入的类型擦除模板类,它可以包装任何签名匹配的可调用对象普通函数和函数指针。

2026-05-25 20:19:02 420

原创 C++ 异常处理:从面试考点到企业级实战(一篇搞定所有坑)

在大型项目中,我们通常会自定义异常类来区分不同类型的错误。继承自标准异常类(通常是实现what()虚函数提供接受错误信息的构造函数支持嵌套异常(C++11 后)企业级自定义异常示例cpp运行public:private:// 业务异常public:// 数据库异常public:// 网络异常public:优先使用异常处理错误,而不是错误码永远使用 RAII 管理资源,这是解决异常安全问题的根本捕获异常时使用引用,避免对象切片。

2026-05-24 17:57:18 386

原创 从可变参数到 emplace:现代 C++ 性能优化的核心组合

C++11 可变参数模板和 emplace 接口,是现代 C++ 最成功的特性组合之一。它们完美体现了 C++"零开销抽象可变参数模板提供了强大的参数转发能力,编译期展开,运行时零开销emplace 接口利用这种能力,彻底消除了容器插入操作的临时对象开销在日常开发中,养成优先使用 emplace 的习惯,可以在不改变代码逻辑的情况下,获得显著的性能提升。这也是区分现代 C++ 程序员和传统 C++ 程序员的重要标志之一。

2026-05-21 19:05:50 521

原创 移动构造和移动赋值

用一个 ** 右值对象(临时对象、被std::move强转后的对象)** 去初始化新对象,转移资源所有权,不深拷贝,原对象变为空 / 可安全析构。类名(类名&& 源对象) noexcept;区别拷贝构造:拷贝是复制资源;移动是抢夺资源。示例伪逻辑:cpp运行char* buf;public:// 移动构造// 直接接管对方内存,不new新内存// 原对象置空,析构时不会重复释放把一个右值对象的资源,转移给已经存在的对象,同样是抢夺资源、不拷贝,原对象置空。

2026-05-21 18:58:53 393

原创 C++ 左右值引用 完全详解(从入门到精通)

很多人学不好引用,根源是没真正分清左右值。不要用 “赋值号左右” 来判断,这是最常见的错误。左值(lvalue)有身份(identity)、不能被移动的表达式。有身份:能取地址、有名字、生命周期超过当前表达式。不能被移动:编译器默认不会把它的资源 “偷” 走。右值(rvalue)没有身份、可以被移动的表达式。没有身份:临时对象、字面量,生命周期只在当前表达式。可以被移动:编译器可以安全地转移它的资源。对于大对象(比如),拷贝操作代价很高(需要分配内存、复制所有元素)。而移动操作只是。

2026-05-21 10:39:27 200

原创 unorder_map 和unorder_set

对于自定义类型,我们需要提供自己的哈希函数。特化std::hash模板自定义仿函数作为模板参数cpp运行// 自定义类型int age;// 方式1:特化std::hash// 组合多个字段的哈希值// 方式2:自定义仿函数// 使用自定义仿函数必须提供哈希函数和相等比较函数相等比较函数必须与哈希函数保持一致:如果两个键相等,它们的哈希值必须相同键类型必须是可复制和可移动的。

2026-05-20 20:07:31 364

原创 Hash表

定义α = 元素个数 / 桶数量为什么不是 1:当 α=1 时,插入一个元素几乎必定发生多次探测,查找退化为 O(n)。为什么不是 0.5:浪费一半内存,不经济。0.75 的来源:实验证明,在随机哈希函数下,线性探测的平均查找长度约为,α=0.75 时查找约 2.5 次,空间利用合理。面试追问“负载因子可以动态调整吗?答:可以。有些实现允许用户指定,例如 Java 的HashMap默认 0.75,也可构造时传入。调整太大会增加冲突,太小浪费内存。考点关键点常见错误冲突解决线性探测/链地址法区别。

2026-05-17 17:18:08 423

原创 红黑树就业面试满分复习指南

第一优先级(今天必须背完):5 条性质 + 最长路径推论 + 工业应用 + Redis 跳表对比第二优先级(明天练会):插入节点的 3 种调整,能手画模拟 3-5 个例子第三优先级(了解即可):删除节点的核心逻辑和 4 种情况的思路直接放弃:所有数学推导、组合计数、理论证明。

2026-05-12 22:09:53 336

原创 AVL树旋转

BF = 左子树高度 - 右子树高度合法值:-1、0、1失衡条件:|BF| = 2(只要出现,必须立刻旋转)

2026-05-12 22:08:24 384

原创 C++ STL map/set 从入门到精通:核心迭代器与 pair 用法全解析

在 C++ 开发中,STL 容器是绕不开的核心技能,而map和set作为关联式容器的代表,凭借红黑树底层实现的 O (logn) 级增删查效率、自动有序性、key 唯一性,成为了面试高频考点、业务开发高频使用的工具。很多初学者对mapset的用法只停留在简单的插入、删除,却始终没搞懂最核心的迭代器和pair—— 而这两个知识点,恰恰是理解和用好这两个容器的关键。本文将从基础定义到实战用法,带大家彻底吃透mapset。

2026-05-08 22:45:11 376

原创 C++ STL map/set 从入门到上手,一篇搞定(附完整可运行示例)

我们之前聊过二叉搜索树(BST)和平衡二叉搜索树,而 C++ STL 里的map 和 set,底层就是封装好的红黑树(一种高效的平衡二叉搜索树)。它们天生自带有序性,插入、删除、查询的时间复杂度稳定在O(logn),是 C++ 开发和考试里最高频的容器之二,今天我们就把它俩讲透,全是可直接跑的示例。cpp运行// 1. 基础定义:默认升序排列的int型set// 2. 自定义排序:降序排列// 3. 列表初始化(自动去重+排序)// 最终存储:1,3,4,5,9cpp运行。

2026-05-07 22:35:02 178

原创 C++ 多态与二叉搜索树 BST 完整复习笔记(含代码踩坑修正)

本文是 C++ 面向对象核心(多态、虚函数、绑定机制)与数据结构二叉搜索树(BST)的全程学习复习笔记,完整覆盖核心原理、代码实现、实操踩坑与 bug 修正,所有内容均来自学习过程中的真实疑问与易错点,适合期末复习、面试复盘使用,重点攻克动态绑定底层逻辑、BST 删除操作的核心难点。多态是面向对象三大特性(封装、继承、多态)的核心,本质是同一接口,不同实现:用基类的统一接口,调用不同子类的差异化实现,实现接口复用与逻辑解耦。核心规则:虚表前半部分顺序和基类完全一致,保证基类指针访问时的兼容性;

2026-05-06 20:49:14 206

原创 C++ 继承与多态 一站式复习指南:从核心原理到面试考点全覆盖

虚表(vtable):编译器为含virtual虚函数的类,自动生成的一张存储虚函数地址的数组。一个类全局只有一张虚表,存放在程序的只读数据段 / 全局静态区,所有该类的对象共享这张表。虚表里按顺序,存储该类所有虚函数的入口地址。虚表指针(vptr):每个含虚函数的对象,内存最开头会隐藏一个指针,指向该类的虚表。32 位系统占 4 字节,64 位系统占 8 字节,是对象内存的第一个成员。纯虚函数:格式为virtual 返回值 函数名(参数列表) = 0;

2026-05-05 21:32:13 407

原创 C++ 模板全解:从特化语法到分离编译的底层逻辑

搞懂了模板的表层语法,我们就进入了 C++ 模板最核心的底层问题:为什么普通函数可以把声明放在.h 头文件、定义放在.cpp 源文件,而模板这么写就会报链接错误?链接的本质,就是找地址。我们先看所有 C++ 开发者都熟悉的普通函数分离写法,对应编译四阶段,看它为什么能完美运行,这是我们对比模板的基准。首先是代码结构:cpp运行// func.h:头文件,仅存放函数声明// func.cpp:源文件,存放函数定义// 函数的具体实现逻辑// main.cpp:调用函数,仅需要包含头文件。

2026-05-02 20:54:38 355

原创 C++ 仿函数(函数对象)从入门到精通 | 复习专用保姆级指南

仿函数(Functor,也叫函数对象),本质是重载了函数调用运算符operator()的类 / 结构体的实例。它是一个对象,却能像普通函数一样被调用,因此得名 “仿函数”。普通函数要保存运行中的状态,只能依赖static静态变量或全局变量,会带来线程安全问题、多次调用状态污染;而仿函数的状态是每个实例独立的,封装在类的成员变量里,互不干扰。本质:仿函数是重载了operator()的类实例,是对象,却能像函数一样调用,完全遵循 C++ 函数重载规则。核心价值。

2026-04-30 19:54:56 379

原创 二叉树和堆排序 Topk

二叉树图顺序:先自己,再左,再右看图走一遍:前序序列:a B D C E F顺序:先把左走完,再自己,再右看图走:中序序列:D B a E C F顺序:左右都走完,最后才访问自己看图走:后序序列:D B E F C a这是topk的实现:

2026-04-21 22:10:20 43

原创 堆(二插堆)

数组长度为n堆排序建堆时,就是从这个位置自底向上调整。堆 = 完全二叉树 + 堆序性质数组存储,下标公式是核心堆排序 = 建堆 + 交换堆顶 + 向下调整高效稳定的排序算法,时间复杂度 O (n log n),原地排序堆排序。

2026-04-20 22:15:42 39

原创 继承理解学习

所以。

2026-04-14 22:54:02 174

原创 做题理解vector

如果空间足够,不扩容时,迭代器不一定失效,比如push_back尾插,元素插入到空间末尾,在不扩容时不会对迭代器产生影响。C.vector删除,当前元素肯定失效,后面元素会牵扯到移动数据,因此删除元素后面的迭代器也会失效。D. vector的删除操作不光会导致指向被删除元素的迭代器失效,删除元素后面的迭代器也会失效。C.vector的删除操作只会导致指向被删除元素及后面的迭代器失效。D.vector的删除操作只会导致指向被删除元素的迭代器失效。A.vector的插入操作一定会导致迭代器失效。

2026-04-14 20:58:39 22

原创 string

const_iterator表示只遍历字符串不改变值,reverse_iterator表示反向遍历,const_reverse_iterator。替换下标表示起始位置 替换长度 相应的字符或者字符串完整的替换进去;他在调用时会重新开辟空间将数据放进去使数据内存只有size的大小;在正序中begin表示开始end表示最后一个字符的下一个。rbegin表示最后一个 rend 表示第一个的前一个;用于删除字符如果只传下标则会删除该下标之后的所有数据;clear()表示清理本字符串;erase(下标,个数);

2026-03-30 20:13:22 37

原创 string

迭代器本身不考虑任何的数据类型只需给他begin和end就可以遍历所有的数据他可以想象是一种指针;但我们在使用字符串的时候用【】加下标来访问相应的值;但是对于大多数容器我们都用迭代器来访问值采用解耦的方法降低耦合减低关联关系;string定义的字符串是可以用[ ]来访问的它的本质也是有operator来实现的运算符重载;我们其实还是可以用s1.lenth()来计算相应的长度;string 可以定义一个字符串。用该函数便可以尾插a这一个字符;这样就实现了字符串的翻转;迭代器:itreator。

2026-03-29 20:27:31 26

原创 模版的使用

通常我们不会去声明类型编译器会自行判断但是如果传入两个类型不同的数据的话就会出现问题,当我们在使用的同样的内部实现但操作类型不一样的时候却要重复定义多个函数来实现。类模版实例化需要名字后面加上<>说明说明书菊类型。这时我们要主动将数据在调用时强转类型。当然我们也可以用两个t来定义模版。模版并不建议声明和定义分离;

2026-03-28 13:22:17 19

原创 动态内存管理

其实当我们在new后加上【】在开辟空间时会多开辟出4个字节的空间在这四个字节里存放着相应开辟个数;它的本质是为delete服务的他说明了delete要销毁的个数。同样的delete也会调用相应的析构函数,来清除相应的数据资源然后再进行内存的销毁;但我们用new来创建相应的自定义的数据时他会自动调用相应的构造函数初始化创建的数据。可以看到这样操作是很方便的那为什莫要进行这样的操作呢。在c++中我们用一种新的开辟空间的方法。那么为什么我们要在这里加上[ ]呢;整体操作起来还是很简单的。

2026-03-28 10:40:43 23

原创 类与对象~

3无缺省值内置类型则被编译器初始化为随机值或0自定义类型到用相应的默认构造如果没有则会报错;如果不想用隐式转换则在相应的构造函数上加上explicit,就不能在实现隐式转换了;在构造函数中每个成员变量都要走初始化列表,它是按照声明顺序走的。友元之间只是单向的A是B的友元B却不能访问A;我们的静态变量应该重新定义他在类中只是声明静态变量属于类不属于对象;1显示在初始化列表中的变量就用该值初始化。它的本质是通过相应的构造函数来初始化相应的对象。内部类默认是外面的那个的友元;static 声明在对象中;

2026-03-24 23:00:00 26

原创 运算符重载

我们在定义自增或者自减类型的运算符重载的时候我们的编译器为了区分我们在声明后置时在参数列表中加了int的伪参数作为站为符;不能被重载的运算符只有5个, 点号 . 三目运算?这里要注意一点当我们只在在类里声明成员函数时,分离后的方法实现要在函数名前加上相应的类域名来限定.关于成员函数有this指针来控制一个参数,实际参数是声明函数中的列表加一;当我们使用时我们以年月日的加法为例演示运算符的重载。定义相应的函数在相应的运算前加上operate,采用定义和实现分离的方法创建的函数。

2026-03-23 00:16:48 27

原创 拷贝构造函数

拷贝构造函数:这是一个拷贝函数他可以被编译器自动生成,换成一句话说它的功能就是用已定义的对象初始化定义一个类;传值调用的本质便是拷贝当我们采用传值调用的拷贝构造函数的时候编译器便会再调用拷贝构造函数形成无限递归程序崩溃。所以说当我们定义的对象有堆这类的自定义类型的时候使用的时候一定要自己创建相应的拷贝函数否则就会出现大问题;另外我们在这里再讲一个小的知识点:自定义的拷贝函数参数设计问题。编译器的拷贝函数是按地址一个字节一个字节拷贝的。由于num指针中的浅拷贝后指向的地址是一样的。

2026-03-21 10:12:20 38 1

原创 类·构造函数和析构函数

它的函数名也是没有ta返回类型也没有返回值,他也是编译器会自行生成的当然我们也可以自行定对于自行生成的析构函数他是只处理栈的内存但是对于new所开辟空间在堆上的数据他是不会处理的所以当我们用堆创建数据时要记得创建相应的析构函数否则会出现内存泄漏;但是为了避免调用发生冲突我们在定义构造函数时通常指选取三中的一种用于重载而缺生函数很明显是不能重载的应为这样的话我们的编译器是不能识别的;首先 我们要知道函数是可以重载那么在我们的类里面构造函数也是这样的。无参构造函数:和他的名字一样他没有参数。

2026-03-19 23:02:56 151

原创 类的相关习题(this指针)

类里面的函数他不在类指针的内存里它是由Call直接创建的我们的指针变量p里面没有函数init 所以在这里它的作用并不是引用而是说明该函数在他的这个类里面方便我们调用;this指针是不可见的他是在编译后默认在形参的第一个位置定义这个this指针来帮助我们访问相应的成员。同时我们还要知道的一个点是在类中函数是不在对象中占用相应的栈的内存的它是由call单独调用的。我们的函数体中没有不同对象的区分那我们编译器是如何识别相应的对象的呢。同时在调用该函数时p的指针会传给this指针。运行崩溃:代码没问题但时出现了。

2026-03-18 22:36:59 317

原创 inline(内联函数)和宏(define)

2内联函数是经过编译器识别后执行的当我们的3函数体代码太多编译器会直接将其以函数处理。正常函数在运行时会存在栈帧的压栈并用call创建一块空间;其调用本身是为了省去Call的时间(当Call的时间大于代码运行时间时)例如:但我们的内联函数的代码有100行调用了1000次。所以内联函数本身适用于代码数倍较少调用次数多的函数。1内联函数本身是为了减少时间是一种内存换空间方法。为了优化宏定义的问题推出了内联函数的定义。而内联函数本身可以理解为一种替换列如。内联:1000*100行。函数:1000+100行。

2026-03-17 21:54:24 132

原创 输入流函数

一、 标准输入函数(面向键盘 stdin )​- 核心用法:按指定格式读取数据,支持 %d (整型)、 %f (浮点型)、 %s (字符串)等格式控制符。​- 注意点:读取字符串时,遇到空格/换行就停止;返回值是成功读取的变量个数,可用于判断输入是否有效(例如 scanf("%d", &a)!=1 说明输入的不是整数)。​- 示例:​​- 核心用法:每次只读取一个字符,包括空格、换行符。​。

2025-12-17 09:55:04 972 3

原创 计算最大公约数,最小公倍数

printf("最大公约数(GCD): %d\n", gcd(num1, num2));printf("最小公倍数(LCM): %d\n", lcm(num1, num2));printf("请输入两个整数: ");// 计算最大公约数 (GCD)// 计算最小公倍数 (LCM)

2025-12-16 00:58:39 226

原创 逗号运算符

逗号运算符的基本形式为:`表达式1, 表达式2, ..., 表达式n`,计算时从左到右依次求值,整个表达式的值为最后一个表达式(表达式n)的值。C语言逗号运算符(`,`)是一种特殊的二元运算符,用于将多个表达式连接成一个复合表达式,其整体值为最后一个表达式的值。这里先计算`3 + 4`(结果丢弃),再计算`5 * 6`,其值`30`作为整个表达式的值赋给`a`。若不加括号,表达式`x++, y++`会被解析为两个独立语句,导致语法错误。- 运算符:在表达式中使用,如`(a, b)`返回`b`的值。

2025-12-16 00:52:34 320

原创 常见错误演示讲解

在该函数中,我们通过malloc开辟了一百个字节的空间。但是,其内部的值已经被销毁了。如果我们没有将它赋值空指针,那么,在判断的时候。他依然会进行打印,然后由于没有值,它会打印随机值,所以说,在开辟空间后,一定要记得去释放。释放之后,一定要再将该返回的地址赋值空指针。然后返回了该数组的数组名,也就是该元素的地址。但是,由于在函数函数之内的变量创建是在栈里面的当该函数的大括号结束时内部的变量以及它的值都会销毁。但是地址一直存在 当我们通过返回的地址p来进行打印的时候,打印的是随机值。本次将以两个例题为例。

2025-12-07 17:00:26 174

原创 结构体相关知识

printf("学号:%d,姓名:%s,成绩:%.1f\n", s1.id, s1.name, s1.score);printf("学号:%d,姓名:%s,成绩:%.1f\n", s2.id, s2.name, s2.score);printf("学号:%d,姓名:%s,成绩:%.1f\n", s3.id, s3.name, s3.score);// 姓名(字符数组)// 方式2:指定成员初始化(推荐,顺序可打乱)// 方式1:顺序初始化(需与成员顺序一致)// 3. 访问结构体成员(用.操作符)

2025-12-06 13:11:18 442

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除