C++从入门到入土
文章平均质量分 81
带大家一起入门C++
星恒随风
长夜破浪伴晓梦,梦晓伴浪破夜长
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
C++异常详解:从 throw、try/catch 到栈展开、RAII 与 noexcept
除数为 0文件打开失败内存申请失败数组访问越界数据库连接失败网络请求失败用户参数非法if (error)return -1;// 处理错误错误码Error CodeC 语言中大量接口都采用这种设计。main↓HttpServer↓↓SqlManager↓Database检查返回值↓判断错误↓继续返回错误码大量正常业务代码会被错误处理代码打断。异常Exceptionpublic:int id), _id(id){}return _id;原创 2026-09-04 23:59:22 · 580 阅读 · 3 评论 -
C++11详解(四):Lambda、std::function与std::bind——彻底理解可调用对象
这种形式调用的东西并不只有普通函数。普通函数函数指针仿函数Lambda成员函数bind 返回对象可调用对象Lambda 表达式std::bind中。它可以理解成:接收一个可调用对象,再绑定或重新安排一部分参数,最终返回一个新的可调用对象。占位符命名空间。新函数第一个参数→ Sub 第一个参数新函数第二个参数→ Sub 第二个参数。原创 2026-09-03 22:27:08 · 336 阅读 · 9 评论 -
C++11详解(三):可变参数模板、emplace与类的新特性
Print(1);参数类型不固定只有 1 个Print();Print(1);类型可以变化参数数量也可以变化可变参数模板参数类型可变参数数量可变Target((args)...可变参数模板转发引用引用折叠完美转发组合起来。emplace则是这套技术在 STL 中最典型的应用之一。=default=delete成员默认初始化overridefinal进一步加强了类的接口约束与可读性。原创 2026-09-03 01:06:00 · 278 阅读 · 9 评论 -
C++11详解(二):右值引用、移动语义、std::move与完美转发
由于strings1↓一块堆空间申请新空间↓复制字符串内容↓让 s2 管理新空间深拷贝vectorstringlistmap自定义资源管理类拷贝代价可能比较高。int a = 10;a * pss [ 0 ]表示一个具有身份、可以持续存在的对象& a & s取得地址。临时结果这些结果通常没有必要长期保留原来的资源。移动C++11 移动语义左值 / 右值↓ ↓T& T&&左值引用 右值引用std::move移动构造 / 移动赋值避免深拷贝。原创 2026-09-02 01:25:31 · 417 阅读 · 13 评论 -
C++11详解(一):统一初始化——列表初始化与 initializer_list
在 C++98 中,不同类型往往使用不同方式初始化。int x;int y;int x = 10;数组 → {}普通变量 → =对象 → ()容器 → 一个一个插入初始化语法并不统一。{}列表初始化class Datepublic:{}private:int _year;int _month;int _day;202511寻找能够匹配的构造函数。可以把它理解成:一个轻量级对象,用来访问编译器为创建的一组只读元素。il↓。原创 2026-09-02 00:38:14 · 406 阅读 · 10 评论 -
C++ 哈希表封装(二):迭代器、operator[] 完整实现
不知道去哪里寻找下一个 BucketHashTable*或者其他 Bucket 位置信息。原创 2026-08-19 21:34:47 · 5354 阅读 · 35 评论 -
C++ 哈希表封装(一):从 HashTable 泛型化到 myunordered_map 与 myunordered_set
InsertFindEraseRehash差不多了。HashTable是一种底层数据结构是提供给用户使用的容器接口。泛型封装真正的问题变成了:能不能只实现一份 HashTable,同时让 unordered_set 和 unordered_map 共用?答案当然是可以。上层容器提供语义↓底层数据结构负责存储"APPLE""apple""Apple"都视为同一个 Key。++i)!Hash也必须按照同样的大小写无关规则计算。Equal 认为相同。原创 2026-08-19 21:31:03 · 5874 阅读 · 21 评论 -
C++ 哈希详解(二):开放定址、哈希桶与 C++ 哈希表底层实现
Key↓↓Bucket不同 Key可能得到相同位置哈希冲突如何处理 Collision展开。开放定址法链地址法这篇文章就从这两个方案出发,逐步手写哈希表。所有 Key↓bucket 5bucket[5]↓Node↓Node↓Node↓...↓N 个需要检查 N 个结点O(N)哈希函数的均匀性对哈希表极其重要。所有已有元素重新计算 bucket。O(N)insert 平均 O(1)?每插入一次都发生而是间隔很多次插入才出现。原创 2026-08-17 20:49:18 · 5229 阅读 · 12 评论 -
C++ 哈希详解(一):从 unordered_map / unordered_set 到哈希函数与哈希冲突
前面学习map和set红黑树O(logN)O(logN)这已经相当高效。但是有些场景中,我们根本不关心元素之间的大小关系。判断一个用户名是否存在统计单词出现次数判断某个 ID 是否已经访问建立学号到学生信息的映射给定一个 Key能不能尽快找到它?如果能够根据 Key直接计算出它大概存在哪里,理论上就不需要像搜索树一样从根开始逐步比较。哈希表Hash Table散列最核心的思想可以概括成一句话:根据 Key 直接计算它对应的存储位置。Key↓↓存储位置Key = 37。原创 2026-08-17 19:44:51 · 6257 阅读 · 7 评论 -
C++ 红黑树封装(二):迭代器、const_iterator 与 operator[] 完整实现 mymap 和 myset
iterator这样的接口。1. 红黑树 iterator 怎么走2. begin/end 怎么表示3. ++ 和 -- 怎么实现4. const_iterator 怎么实现5. 为什么 set 不能修改元素6. 为什么 map 只能修改 value7. insert 为什么返回 pair<iterator,bool>8. operator[] 为什么依赖 insertT,T&,T*> Iterator;T,原创 2026-08-16 22:15:42 · 6114 阅读 · 13 评论 -
C++ 红黑树封装(一):从 SGI-STL 源码理解如何用一棵红黑树实现 map 和 set
插入查找自动平衡但如果停留在这里,它仍然只是一种数据结构。setmapmultisetmultimap容器封装set<int> s;set 存 keymap 存 key-value看起来完全不是一种数据结构。但实际上,它们有一个非常重要的共同点:都需要按照 key 进行有序存储和搜索。set红黑树map完全可以共用一套红黑树实现。真正困难的问题因此变成:如何设计一棵足够泛型的红黑树,让它既能保存K,又能保存pair<K,V>?这正是这一篇文章要解决的问题。原创 2026-08-16 22:11:12 · 6179 阅读 · 9 评论 -
C++ STL详解 红黑树(二):C++插入实现、旋转修复与合法性验证
红黑树为什么能够保持近似平衡?插入以后为什么需要变色和旋转?这一篇正式进入代码实现。1. 红黑树结点2. 左旋与右旋3. BST 插入4. 红黑树插入修复5. Find 查找6. 红黑树合法性验证红黑树的代码虽然看起来比较长,但真正复杂的部分其实只有插入修复。第一阶段:BST 插入第二阶段:新结点染红第三阶段:如果父结点为红,修复红红冲突→ 变色→ 向上继续→ 判断 LL / RR / LR / RL→ 旋转→ 变色→ 结束curparentuncle。原创 2026-08-14 23:30:30 · 6962 阅读 · 20 评论 -
C++ STL详解 红黑树(一):从基本性质到高度证明与插入调整
在学习红黑树之前,我们首先需要知道它到底解决了什么问题。4/ \2 6/ \ / \1 3 5 7log₂NO(logN)但是普通二叉搜索树并不会主动维护自己的结构。12345O(N)O(N)所以我们需要一种能够自动控制高度的二叉搜索树。AVL 树是一种解决方法,而红黑树则是另一种非常经典的解决方案。红黑树并不像 AVL 树那样严格要求左右子树高度差不超过 1,而是通过一些颜色规则间接约束树的高度,因此红黑树是一种近似平衡的二叉搜索树。原创 2026-08-14 22:27:22 · 7083 阅读 · 22 评论 -
C++ AVL 树详解(二):四种旋转、完整代码与平衡验证
按照 BST 规则插入↓沿祖先路径更新平衡因子↓平衡因子为 0:停止平衡因子为 ±1:继续平衡因子为 ±2:旋转真正实现 AVL 树时,难点主要集中在旋转。二叉搜索树的大小关系左孩子指针右孩子指针父指针整棵树的根指针局部子树与上一层的连接结点的平衡因子右单旋左单旋左右双旋右左双旋最后给出一套可以直接在 Linux 环境中编译运行的完整 C++ 实现。假设失衡结点为parent说明 parent 左边比右边高 2。再看 parent 的左孩子subL。原创 2026-08-05 01:26:52 · 5433 阅读 · 29 评论 -
C++ AVL 树详解(一):平衡因子、树高控制与插入过程
左子树中的关键字小于根右子树中的关键字大于根左右子树仍然是二叉搜索树借助这个规则,我们可以根据关键字大小决定向左还是向右查找。但是,普通二叉搜索树有一个明显的问题:它只规定了关键字之间的大小关系,却没有限制树的形状。查找7O(log N)O(N)AVL 树就是为了解决这个问题而出现的。普通二叉搜索树↓树高决定操作效率↓限制左右子树高度差↓引入平衡因子↓按照 BST 规则插入↓沿祖先路径更新平衡因子↓发现不平衡结点↓通过旋转恢复平衡。原创 2026-08-04 22:33:19 · 5401 阅读 · 21 评论 -
C++ STL 详解:map 与 multimap 的使用、operator[]
set某个关键字是否存在?而实际开发中,我们经常不只是想找到一个关键字,还想找到它对应的信息。英文单词 -> 中文解释学号 -> 学生成绩商品编号 -> 库存数量用户名 -> 用户资料文件名 -> 文件大小这种“一个关键字对应一个值”的关系,称为映射关系。C++ STL 中的map就是用来保存这种关系的有序关联式容器。key :用于查找和排序value :与 key 关联的数据map和set的关系pair与键值对map的构造和遍历为什么 key 不能修改,而 value 可以修改。原创 2026-07-30 00:51:17 · 5339 阅读 · 22 评论 -
C++ STL 详解:set 与 multiset 的使用、区间查询和算法应用
int main()students.insert({1003, "张三"});students.insert({1001, "李四"});students.insert({1002, "王五"});return 0;原创 2026-07-29 20:48:33 · 5356 阅读 · 15 评论 -
C++ 二叉搜索树详解:从一个结点到完整 BST 实现
在学习普通二叉树时,我们主要关注的是树的结构,以及前序、中序、后序、层序等遍历方式。但普通二叉树有一个问题:结点之间没有统一的大小关系。假设现在要在一棵普通二叉树中查找数字13,除了把整棵树遍历一遍,我们通常没有更好的办法。因为站在某个结点上时,并不知道目标应该在左子树还是右子树。较小的数据放在左边较大的数据放在右边正是这条看起来很简单的规则,让树具备了定向查找、插入和删除的能力。这时树的方向会与默认升序规则相反,但只要所有操作都使用同一个比较器,结构仍然是自洽的。原创 2026-07-29 00:25:06 · 5727 阅读 · 5 评论 -
C++ 多态底层原理:静态绑定、动态绑定、虚函数表与工程实践
虽然ptr的类型是Base*编译器如何知道指针实际指向哪种对象?静态绑定和动态绑定有什么区别?什么是虚函数表和虚函数表指针?派生类重写虚函数后,虚表发生了什么变化?为什么含有虚函数的对象可能会变大?为什么构造和析构期间不会调用更派生类版本?如何保存一组不同类型的多态对象?应该在什么时候使用?虚函数会带来多大性能开销?本文主要从底层原理和实际工程使用两个角度,继续讲解 C++ 多态。对象保存虚表指针虚表保存虚函数地址基类指针或引用调用虚函数。原创 2026-07-27 00:44:22 · 5566 阅读 · 26 评论 -
C++ 多态基础:虚函数、重写、抽象类与虚析构
继承解决了类之间的代码复用问题,但仅仅有继承,还不能让程序根据对象的实际类型自动执行不同的行为。普通人:全价买票学生:优惠买票军人:优先买票如果程序通过大量if-elsecout << "全价买票" << endl;cout << "优惠买票" << endl;cout << "优先买票" << endl;多态提供了一种更自然的方式:调用者只面向统一的基类接口,具体执行哪个版本,由对象的实际类型决定。静态多态和动态多态运行时多态的构成条件虚函数和虚函数重写override和。原创 2026-07-26 01:31:46 · 5254 阅读 · 12 评论 -
C++ 继承进阶:默认成员函数、多继承、虚继承与组合设计
派生类构造时,基类部分由谁初始化?拷贝构造和赋值运算符是否需要处理基类?为什么构造顺序是从基类到派生类,析构顺序却正好相反?基类析构函数什么时候必须是虚函数?友元关系和静态成员会不会被继承?多继承为什么会产生二义性?菱形继承为什么会造成数据冗余?虚继承如何让多个路径共享同一个基类子对象?继承和组合到底应该如何选择?这些内容看起来比较分散,实际上都围绕一个核心问题:一个派生类对象中,不仅有派生类自己的成员,还包含基类子对象。接下来我们就围绕着这点展开。原创 2026-07-24 23:59:33 · 5599 阅读 · 14 评论 -
C++ 继承(1):从代码复用、访问控制到对象切片与名字隐藏
继承是 C++ 面向对象部分非常重要的一块内容。在学习继承之前,我们已经接触过函数复用、模板复用和 STL。它们解决的都是“相同代码不要重复写”的问题,而继承解决的是类层面的复用。例如,学生和老师都具有姓名、年龄、电话和地址,也都需要进行身份认证。如果分别在Student和Teacher中定义这些成员,不但代码重复,后续修改起来也比较麻烦。继承允许我们把公共部分抽取到一个基类中,再让不同的派生类在此基础上继续扩展。不过,继承并不只是把一个类的代码复制给另一个类。基类和派生类的关系public。原创 2026-07-24 23:14:19 · 5574 阅读 · 5 评论 -
C++ STL 队列详解:queue 的使用、经典应用与简单模拟实现
生活中排队是一件很常见的事。先到的人先接受服务,后到的人排在队尾等待。先进先出FIFOC++ STL 提供了queue容器适配器,可以直接实现队尾入队、队头出队。广度优先搜索二叉树层序遍历任务调度消息缓冲请求排队打印任务管理生产者和消费者模型本文从queue的基本接口开始,逐步讲解它的底层要求、典型应用、两个栈实现队列,以及一个简化版queue的模拟实现。队列是一种操作受限的线性数据结构。push(1);push(2);push(3);原创 2026-07-22 19:22:42 · 5747 阅读 · 5 评论 -
C++ STL 栈详解:stack 的使用、经典题目与简单模拟实现
在数据结构中,栈算是比较容易理解的一种结构。它的规则很简单:最后放进去的元素,最先被取出来。后进先出LIFOC++ STL 已经提供了stack,使用起来并不复杂。但只记住push()和pop()栈为什么只能访问栈顶?pop()为什么不返回被删除的元素?stack为什么没有迭代器?什么是容器适配器?为什么 STL 默认使用deque作为底层容器?如何用已有容器简单模拟一个栈?栈是一种操作受限的线性数据结构。123栈顶↓┌───┐│ 3 │├───┤│ 2 │。原创 2026-07-21 18:30:02 · 5660 阅读 · 11 评论 -
C++ STL 详解:list 的使用、迭代器失效、模拟实现与 vector 对比
在 C++ STL 中,vector和list都是非常重要的序列式容器。如果说vector更像是“可以自动扩容的数组”,那么list更像是“一串用指针连接起来的节点”。很多同学刚学list的时候,会觉得它没有vector好用:不能下标访问,遍历起来还要用迭代器,看起来没有那么直观。但list适合频繁插入和删除插入时不会整体搬移元素删除某个节点时,通常只影响被删除节点对应的迭代器底层结构非常适合帮助我们理解链表和 STL 迭代器所以学习list。原创 2026-07-21 13:04:26 · 5820 阅读 · 19 评论 -
C++ STL 详解:vector 的使用、扩容、迭代器失效与底层模拟实现
在 C++ 里,如果只让我们选一个最常用的 STL 容器,vector大概率会排在第一位。它像数组一样支持下标访问,又比原生数组灵活,可以自动扩容,也能配合 STL 算法一起使用。刷题、写项目、处理一组连续数据时,vector基本都是绕不开的。很多同学刚学vector时,容易停留在“会用push_back、会用下标访问”的阶段。size()和capacity()到底有什么区别?reserve()和resize()为什么不能混用?为什么push_back之后,原来的迭代器可能会失效?为什么删除。原创 2026-06-18 23:45:55 · 1258 阅读 · 17 评论 -
C++ string 类详解:常用接口、OJ 场景与模拟实现中的深浅拷贝
上一篇我们从 STL 的整体结构出发,介绍了string在 C++ 标准库中的位置。string到底怎么用?输入一整行,求最后一个单词长度。因为它遇到空格就停止。不过如果字符串末尾可能有空格,需要先处理尾部空格。浅拷贝也叫位拷贝。意思是:只把对象中的成员变量值原样复制一份。如果成员变量是普通int,没问题。但如果成员变量是指针,就会把地址复制过去。结果就是多个对象共享同一块资源。深拷贝的核心是:每个对象都拥有自己独立的资源。对于String来说,拷贝时不能只复制_str。原创 2026-06-16 17:04:55 · 3163 阅读 · 16 评论 -
C++ string 入门(一)
标准模板库。Standard:标准Template:模板Library:库简单理解:STL 是 C++ 标准库的重要组成部分,是一套基于泛型编程思想的数据结构与算法框架。它不是只提供“容器”,也不是只提供“算法”,而是把容器、算法、迭代器、函数对象、适配器、空间配置器等组件组合成了一套完整体系。原创 2026-06-15 00:33:03 · 502 阅读 · 14 评论 -
C++ 模板初阶:从泛型编程、函数模板到类模板,一篇打通基础概念
泛型编程可以简单理解为:编写与具体类型无关的通用代码。所谓“泛型”,就是不提前绑定某一个具体类型。比如交换两个变量这件事,本质上并不关心它们是intdouble,还是string。那么这套交换逻辑就能成立。这就是泛型编程的价值:把“类型变化”交给编译器,把“通用逻辑”保留下来。在 C++ 中,模板就是泛型编程最基础、最核心的工具。函数模板不是一个普通函数。它更像是一个“函数生成规则”。它描述了一类函数的共同逻辑,具体类型在使用时再由编译器确定。这里的T不是一个真实类型。原创 2026-06-13 22:49:16 · 898 阅读 · 15 评论 -
C++ 内存管理详解:从内存分区、malloc/free 到 new/delete
free(p1);申请一块和A对象一样大的空间;释放这块空间。构造函数不会调用;析构函数不会调用。严格来说,p1指向的只是“一块原始内存”,还不能算一个真正完成构造的A对象。定位new,也叫 placement new。它的作用是:在一块已经分配好的原始内存上,显式调用构造函数创建对象。只是申请了一块原始空间。才是在这块空间上调用构造函数,把它变成一个真正的A对象。原创 2026-06-12 16:39:02 · 845 阅读 · 17 评论 -
C++ 类和对象入门(六):友元、内部类、匿名对象和编译器优化
前一篇我们讲了初始化列表、explicit和static成员。友元内部类匿名对象对象拷贝时的编译器优化这些内容不像构造函数、析构函数那样每天都会写,但它们在理解 C++ 类的边界、对象生命周期、编译器行为时非常重要。其中友元和内部类主要和“封装边界”有关。匿名对象和编译器优化主要和“临时对象生命周期、拷贝优化”有关。友元函数是在类内部用friend声明的外部函数。它不是类的成员函数,但可以访问类的私有成员和保护成员。原创 2026-06-11 14:03:12 · 580 阅读 · 12 评论 -
C++ 类和对象入门(五):初始化列表、explicit 和 static 成员详解
学到 C++ 类和对象的后半部分,很多同学会发现一个现象:前面已经学过构造函数了,为什么后面还要“再探构造函数”?原因很简单。int _month;int _day;这段代码能用,也很直观。但是从 C++ 的对象初始化机制来看,它并不是最完整、最推荐的写法。因为在 C++ 中,对象成员不是进入构造函数体之后才“出生”的。它们在构造函数体执行之前,就已经要完成初始化了。原创 2026-06-10 11:41:23 · 807 阅读 · 22 评论 -
C++ 类和对象入门(四):日期类 Date 的运算符重载实现详解
构造函数析构函数拷贝构造函数赋值运算符重载深浅拷贝运算符重载的基本规则这一篇直接从一个完整案例入手:日期类 Date 的实现。带大家一起练习一下运算符重载,。d1 < d2;d1 == d2;d1 + 100;d2 - 10;d2 - d1;++d1;d1++;cout << d1;cin >> d1;这些写法看起来很自然。但对编译器来说,Date是我们自己定义的类型,它不知道两个日期怎么比较,也不知道日期加 100 天该怎么算。原创 2026-06-09 13:53:07 · 683 阅读 · 14 评论 -
C++ 类和对象入门(三):拷贝构造、赋值运算符重载和深浅拷贝
构造函数析构函数构造函数负责对象创建时初始化。析构函数负责对象销毁前清理资源。拷贝构造函数赋值运算符重载这两个函数都和“对象拷贝”有关。这一篇的目标是讲清楚三件事:第一,什么时候调用拷贝构造?第二,什么时候调用赋值运算符重载?第三,为什么有资源管理的类不能依赖默认浅拷贝?这一篇主要讲了拷贝构造、赋值运算符重载和运算符重载基础。用已有对象初始化新对象;参数必须使用当前类类型的引用;常写成const 类名&;传值传参、传值返回可能触发拷贝构造。原创 2026-06-08 16:43:31 · 508 阅读 · 14 评论 -
C++ 类和对象入门(二):默认成员函数、构造函数和析构函数详解
这一章要讲的内容是:默认成员函数。所谓默认成员函数,就是即使我们不写,编译器在某些情况下也会自动生成的成员函数。构造函数析构函数拷贝构造函数赋值运算符重载另外还有取地址运算符重载,C++11 之后还有移动构造和移动赋值。入门阶段先重点理解前四个。构造函数:对象创建时负责初始化析构函数:对象销毁时负责清理资源它们解决的问题很现实:对象创建时,怎么保证内部数据是合理的?对象销毁时,怎么保证申请过的资源被释放?原创 2026-06-07 23:19:36 · 819 阅读 · 9 评论 -
C++ 类和对象入门(一):从 class、访问限定符到 this 指针
类和对象。很多同学刚看到类时,会觉得它像是“升级版结构体C 语言结构体只能放数据;C++ 的类既可以放数据,也可以放函数;数据和函数放在一起之后,代码看起来更像一个整体。这个理解没错,但还不够完整。C++ 类和对象真正重要的地方在于:它把数据和操作数据的函数封装到一起,并通过访问权限控制外部如何使用对象。比如我们实现一个栈。ST s;STInit(&s);STPop(&s);Stack s;s.Init();s.Push(1);s.Pop();原创 2026-06-06 14:52:29 · 730 阅读 · 13 评论 -
C++入门(二):函数重载、引用、const引用和 inline 内联函数
int& ra;// 错误,引用必须初始化int a = 10;引用不是“空别名”。既然是别名,就必须一开始说明它是谁的别名。这一篇主要讲了 C++ 入门中非常重要的几个增强语法。同一作用域中允许同名函数;要求参数列表不同;返回值不同不能构成重载;重载解析发生在编译阶段。引用是已有变量的别名;引用定义时必须初始化;引用一旦绑定,不能再绑定其他对象;引用传参可以修改外部变量,也能减少拷贝;引用返回可以返回对象本身,但不能返回局部变量引用。可以引用 const 对象;原创 2026-06-05 11:06:56 · 819 阅读 · 8 评论 -
C++入门(一):第一个 C++ 程序、命名空间、输入输出和缺省参数
如果你已经学过 C 语言,再来看 C++,第一感觉可能是:这不就是 C 语言加了一些新语法吗?C++ 确实兼容 C 语言的大多数语法,所以很多 C 语言程序放到 C++ 文件中依然可以运行。但是 C++ 不只是“更大的 C”,毕竟它的名字叫 “” ,它在 C 的基础上引入了命名空间、函数重载、引用、类和对象、模板、STL 等一系列机制。这一篇先从 C++ 入门最基础的几个点开始讲起namespace 命名空间名 {// 变量 // 函数 // 类型 }int val;Node* next;原创 2026-06-04 14:05:19 · 555 阅读 · 3 评论
分享