- 博客(50)
- 收藏
- 关注
原创 什么情况下会调用拷贝构造函数
本文摘要:拷贝构造函数在C++中主要用于三种场景:1)对象初始化时直接复制另一个对象(如Person p2=p1);2)函数参数按值传递时创建副本(如printPerson(p1));3)函数返回对象时理论上会生成临时副本(但编译器优化NRVO可能消除拷贝)。文章通过Person类示例演示了这三种情况,并与拷贝赋值运算符(operator=)进行区分,同时指出容器操作(如vector.push_back())也会触发拷贝构造。
2026-07-06 15:42:21
173
原创 静态绑定和动态绑定的介绍
【摘要】静态绑定在编译期确定函数地址,适用于普通函数调用、模板实例化等场景。动态绑定在运行时通过虚函数表确定调用,需满足公有继承、虚函数重写和基类指针/引用指向子类对象三要素。特别注意:1)默认参数采用静态绑定原则;2)构造函数和析构函数中调用虚函数会退化为静态绑定,始终执行当前类的函数版本。实验显示,基类指针调用虚函数时函数体使用子类实现但参数值沿用基类默认值,且在构造/析构阶段虚函数不会触发多态行为。
2026-07-06 15:41:10
205
原创 C++所有的构造函数
本文总结了C++中的6类构造函数及其特性:1)默认构造(无参或全默认参数);2)有参构造(单参构造支持隐式转换,可用explicit禁止);3)拷贝构造(const左值引用参数);4)移动构造(C++11引入,右值引用参数);5)委托构造(复用其他构造逻辑);6)继承场景构造(需显式调用父类构造)。编译器在特定条件下自动生成这些特殊成员函数(默认构造、拷贝/移动构造和赋值操作符),但若自定义相关函数会阻止自动生成。聚合初始化适用于无自定义构造的简单类。
2026-07-06 15:39:31
262
原创 析构函数可以抛出异常吗?为什么不能抛出异常?除了资源泄露,还有其他需考虑的因素吗?
在我们不做过多处理的情况下,析构函数是绝对不能抛出异常的,这会直接导致我们的整个程序被强制终止。
2026-07-06 01:34:55
198
原创 WSL2 独显性能完全解锁指南:让 Linux 图形与计算飞起来
在传统的双系统或虚拟机中,Linux 需要安装专有的 NVIDIA 驱动才能识别显卡。但 WSL2 采用了一种革命性的架构——。
2026-05-08 19:10:36
804
1
原创 彻底解决 WSL2 中 ROS2 RViz2/Gazebo 卡顿:开启 GPU 硬件加速全记录
在 WSL2 中搞定 OpenGL 硬件加速,关键在于理清OpenGL -> Mesa D3D12 -> Windows DX12 -> 显卡这条链路,并排楚 Ubuntu 22.04 带来的包版本陈旧、依赖冲突以及双显卡选择问题。希望这篇文章能帮到更多在 WSL2 下开发 ROS2 的朋友,让大家把精力留在算法开发上,而不是被环境配置卡住脚步!
2026-05-08 19:05:40
1203
2
原创 宏定义与typedef和inline的区别
宏定义是中预处理阶段进行的字符串替换,它可以实现类似typedef和inline的功能,不过宏定义缺少类型检查与一些特有功能。
2026-04-13 14:20:24
204
原创 什么是机器学习,用线性回归模型带你了解机器学习
机器学习其核心是让计算机系统通过数据和经验自动改进性能,而无需显式编程。机器学习主要分为监督学习与无监督学习,在学习机器学习时很重要的一点是,应用学习算法的实用建议,学习算法就像是一套工具你只有熟练的使用它,才能完成你的工作线性回归用于建立输入变量(x)和连续型输出变量(y)之间的线性关系,目的是预测一个数值(如房价、温度、销售额等)。这是一个最简单的线性回归公式,其中w被称为权重b被称为系数或者偏置,机器学习的目的就是通过给定的训练集,不断的调整权重与系数 ,找到一条直线,使得预测值 与实际观测值
2025-04-11 15:04:06
1121
原创 详解数据结构线性表 c++实现
线性表是一种非常基础且重要的数据结构,它是具有相同数据类型的 n(n≥0)个数据元素的有限序列。这里的 “有限” 意味着元素的数量是确定的,“序列” 则表示元素之间存在着顺序关系。
2025-04-04 12:31:00
808
原创 详细介绍平衡二叉树 c++实现
(AVL树)是一种,由Adelson-Velsky和Landis于1962年提出。其核心目标是,从而避免普通二叉搜索树(BST)在插入有序数据时退化为链表的性能问题。每个节点的AVL树要求所有节点的平衡因子绝对值。若某个节点的平衡因子超出范围,则触发以恢复平衡。AVL树也是二叉搜索树,插入搜索删除都是一样的,只是每次操作完后检查一次是否失衡![[平衡二叉树旋转规则.jpg]]
2025-03-31 14:23:27
703
原创 详解数据结构之树、二叉树、二叉搜索树详解 C++实现
树是n ( n>=0 )个结点的有限集。n=0时称为空树。图中的G H I J为叶子节点,B C D E F为分支结点也叫做内部结点,整颗树的度为3因为节点D的度为3。
2025-03-30 16:03:08
1255
原创 详解c++中的可调用对象,std::function、Lambda表达式、std::bind等
可调用对象用处广泛,比如在使用一些基于范围的模板函数时(如 sort()、all_of()、find_if() 等),常常需要我们传入一个可调用对象,以指明我们需要对范围中的每个元素进行怎样的处理。又比如,在处理一些回调函数、触发函数时,也常常会使用可调用对象。()等。上面演示了最简单的可调用对象。
2025-03-27 21:06:31
1206
原创 详解c++的类型转换,static_cast、dynamic_cast、const_cast、reinterpret_cast运算符
c中变量的数据类型可以强制转换为其他数据类型。但由于这种C风格的类型转换可能会出现一些问题,即过于松散的情况和因此 C++ 提出了更加规范、严格的类型转换,添加了四个类型转换运算符,进而更好的控制类型转换过程。
2025-03-27 17:37:32
1150
原创 详细讲解c++中线程类thread的实现,stl源码讲解之thread
本节我们来详细介绍一下c++中的线程类thread,在讲解的过程中会用到大量模板的知识,可以去看是一个 SFINAE(Substitution Failure Is Not An Error)技巧,用于禁止使用thread对象作为可调用对象来构造新的thread对象。
2025-03-26 21:49:59
1025
原创 c++手撕协程库,实现生成器与自定义可等待对象
Context定义了我们用到的14个寄存器,而swap_context函数就是我们代码层面用来调用汇编的接口,这个函数只有声明没有定义,在连接阶段会将汇编代码与当前的声明合并,详细的c++编译过程可以看。协程是用户态的线程,它需要由程序来进行调度,如上下文切换与调度设计都需要程序来设计,并且协程运行在单个线程中,这就成就了线程的低成本,简单讲协程就是一种可以被挂起与恢复的特殊函数。你可以简单的理解为就是一个函数名,冒号后面是函数的运行逻辑,我们分为两部分保存于恢复之间用换行分隔,
2025-03-25 17:29:37
1057
原创 详解c++20的协程,自定义可等待对象,生成器详解
自定义可等待对象需要满足特定的接口要求,主要涉及和这三个成员函数。:用于判断是否可以立即恢复协程的执行。若返回true,协程会马上恢复;若返回false,协程就会被挂起。:在协程挂起时调用,这里可以执行异步操作。在示例中,使用一个新线程来模拟异步操作,操作完成后恢复协程。:在协程恢复执行时调用,返回异步操作的结果。return 42;});// 输出: 42return 0;
2025-03-24 23:18:15
2232
原创 详细解释计算机系统中的大小端
在计算机系统中,对于跨越多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中最小的地址,例如,假设一个类型为int的变量x的地址为0x100,也就是说,地址表达式&x的值为0x100。那么,(假设数据类型int为32位表示)x的4个字节将被存储在内存的0x100、0x101、0x102和0x103位置。这种排列方式有两种,某些机器选择在内存中按照从最低有效字节到最高有效字节的顺序存储对象,而另一些机器则按照从最高有效字节到最低有效字节的顺序存储。在最前面的方式,称为。在最前面的方式,称为。
2025-03-22 21:47:28
267
原创 Amdahl 定律
a表示我们提升部分初始耗时比例,k是我们的提升倍率,通过这个公式我们可以轻松的得知对每一部分的提醒,对整个系统带来的影响是多少。
2025-03-22 21:46:41
353
原创 计算机时钟周期
是描述硬件操作时序的基本概念,它决定了计算机各部件协调工作的节奏,CPU内部时钟振荡器产生的周期性脉冲信号就是时钟周期,是计算机系统的最小时间单位。在计算机系统中cou运行命令的时间是按时间周期来算的,比如运行最基本的加分运算可能需要1周期完成,对于同架构的cpu这个周期是一样的,不过实际运行时间不同,这是因为不同处理的主频不一样导致一时钟周期需要的时间也不一样。拿苹果的m1芯片举例,它的主频是3.2GHz,时钟周期是3.2 * 10的9次方分之1,所以一时钟周期是31纳秒。
2025-03-22 21:45:47
530
原创 简述计算机系统中的抽象,进程、线程、虚拟内存与文件抽象
计算机系统中的一个重大主题就是提供不同层次的抽象表示,来隐藏实际实现的复杂性。在处理器里,指令集架构提供了对实际处理器硬件的抽象。使用这个抽象,机器代码程序表现得就好像运行在一个一次只执行一条指令的处理器上。底层的硬件远比抽象描述的要复杂精细,它并行地执行多条指令,但又总是与那个简单有序的模型保持一致。
2025-03-22 12:47:51
986
原创 详解计算机储存系统,局部性原理,高速缓存与寄存器的作用
根据机械原理,较大的存储设备要比较小的存储设备运行得慢,而快速设备的造价远高于同类的低速设备。比如说,一个典型系统上的磁盘驱动器可能比主存大1000倍,但是对处理器而言,从磁盘驱动器上读取一个字的时间开销要比从主存中读取的开销大1000万倍。针对这个原因,计算机系统中的储存结构被设计成了多层,根据访问速度来排列,最顶层的访问速度最快相应的造假也更高储存容量更少,低层的造价便宜容量大,访问速度也更低,这样设计的主要原因是上一层的存储器作为低一层存储器的缓存,这种设计有效的原因是使用了。
2025-03-21 19:49:51
1175
原创 c++简单实现redis
本节我们一步一步实现redis的基本数据类型,redis的数据类型讲解可以看核心redis类的实现我们通过这个类来控制整个redis系统,这是一个单例类,commandTypes是各个设计命令对应的类型,比如set对应string,hset对应hash,redis这个成员变量是所有的键值对,这个函数继承了一个单例模板类,我们通过you hao,它只对外开放一个command接口,参数和返回值都是一个字符串,下面是具体实现。
2025-03-20 20:26:41
1221
原创 c++实现单例模板类
上面就是我们单例模板类的全部类,很简单的实现GetInstance函数用来获得实例,如果你是c++11以下的版本,你可以需要额外做一下线程安全,因为在c++11之前static是不保证线程安全的,我们delete掉了移动构造和移动赋值函数,确保类的唯一形,我们还将构造与析构函数设置成为了protected,这确保了在代码中我们无法构造单例类。今天我们来实现一个懒汉式的单例模板类,我们只需要继承这个类就可以实现单例,懒汉式是在第一次被使用时才进行初始化,这叫做延迟初始化。
2025-03-20 17:09:54
315
原创 Linux中的epoll简单使用案例
允许一个进程或线程同时监控多个网络 sockets 的状态。它通过单个系统调用(select)来检查多个 sockets 是否有数据可读、可写或是否有异常。Linux 提供了多种 I/O 复用技术,包括上面提到的 select、以及 poll、epoll。
2025-03-17 22:12:43
923
原创 Linux网络编程,创建api的使用方式
本节将详细介绍Linux网络编程,主要包括套接字的作用,Linux的模型epoll,在网络编程中,就像是网络世界的。每一个联网的应用程序,为了能够互发消息,都会使用到这样一个端口。这个端口允许数据从一个程序流向另一个程序。简而言之,套接字是应用程序用来在网络上交流的桥梁。而允许一个进程或线程同时监控多个网络 sockets 的状态。它通过单个系统调用(select)来检查多个 sockets 是否有数据可读、可写或是否有异常。
2025-03-17 20:16:48
913
原创 简答介绍Redis的基本使用
Redis是一款高性能的key-value数据库,Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,同时还提供list,set,zset,hash等数据结构的存储。Redis支持数据的备份,即master-slave模式的数据备份,并且Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。Redis的操作相当简单,我们可以使用redis-cli工具在命令行连接redis,对于redis的命令相当简单,详看下面的介绍。
2025-03-16 19:13:20
677
原创 详解c++的编译过程,如何从源文件到可执行文件到
本节详细介绍c++的编译过程,c++从代码到可执行文件有四个阶段:我们可以使用这一命令进行预处理,预处理后的文件还是文本文件可以打开查看以.i为结尾这一阶段主要处理以井号#开头的代码,比如, , ,对代码进行一个初步的处理,并且会把所有注释删除,通过#include将头文件的实际内容放入当前文件中,主要有两种格式 或 ,对于尖括号的格式,编译器会在默认的头文件搜索路径(通常是标准库头文件所在的系统目录)中查找指定的头文件。例如像、这样的标准库头文件,通常使用尖括号来引用,对于双引号格式,编译器会优先在当
2025-03-16 15:40:53
2848
原创 c++详解模板泛型编程,详解类模板的实现为什么不能放在cpp文件
泛型编程是一种编程范式,它允许程序员编写与类型无关的代码,从而在编译期确定具体的类型。我们通过模板编写一个函数可以让编译器,自动生成对应类型的实现,这大大减少了重复代码的出现,还提高了代码的可维护性和可扩展性,很重要的一点是模板有特性。
2025-03-15 22:37:58
1065
原创 c++异常处理简单介绍 try catch throw三者的作用
c++中通过try catch throw这三个关键字处理异常,我们为什么要处理异常呢,为什么要用专门的异常处理来处理异常呢,这是本文将要解决的几个问题,我们会一一解答疑惑,异常处理的主要作用是,让我们的程序更健壮,当遇到不可预测的问题时可以做出处理,而不是直接崩溃,当发送错误时可以让程序执行备选方案,如果不得不接受程序时可以提前做一些必要的工作,如将内存中的数据写入文件、关闭打开的文件、释放动态分配的内存空间等。
2025-03-15 17:03:21
670
1
原创 c++详解移动语义,右值引用与move函数的作用,noexcept关键字在移动构造与移动赋值运算符中的重要性
这是c++ 11新添加的特性,设计的目的是为了避免不必要的拷贝开销,通过提升性能,它可以在不拷贝的情况下移动大型资源,它所做的就是将现有资源的所有权交给其他对象,而传统的拷贝需要进行一次内存分配这是很大的开销,移动语义相较于拷贝性能提升相当明显,移动后的源对象处于,即保证可安全析构和重新赋值,但具体成员值由实现决定(可能为空、残留值等)。继续访问其值前必须先重置状态。
2025-03-14 19:27:20
771
原创 c++智能指针详解,如何防止循环引用
智能指针是c++ 11标准,添加的用于管理内存资源的类,通过智能指针我们可以,轻松的对内存进行分配与释放,这使得我们不再需要,为手动管理内存的繁琐而烦恼了,主要有三个智能指针,分别是unique_ptrshared_ptrweak_ptr,我们下面一一介绍我们先来看看智能指针的基本使用上面这一部分代码,如果没有智能指针是不可以出现~Test析构的,而使用了智能指针后当func1函数退出时,我们创建的资源就自动被释放了,这就是智能指针的魅力,利用RAII思想完美实现资源的管理,真的非常方便且高效。
2025-03-13 22:06:04
1305
原创 详解c++中的const关键字
c++中const关键字可以实现将一个变量或者函数,限定为只读不可进行修改的功能,它的作用是很大的,const可以避免程序员在代码中意外修改某些本应保持恒定的值,并且它还可以限定指针或引用,使其无法通过它们修改所指向的对象,通过const,可以增强代码的安全性和可读性,明确标识出不应被修改的部分,同时编译器会强制检查这些约束。下面再仔细讲讲,const在c++的各种应用。
2025-03-13 19:18:04
541
原创 C++基础内存管理讲解,如何避免常见的内存问题,堆栈内存讲解
内存管理是c++变成中很重要的一环,这是编写高效可靠c++的必要条件,这也是c++与其他高级语言最大的区别,其他的语言都提供了高级的gc机制,而c++没有这就难住了很大一部分人了,对于高手来说这是高效程序的关键,对于菜鸟这就是噩梦啊,经常出现的野指针,忘记delete的内存严重影响了运行与开发效率。
2025-03-12 22:58:21
721
原创 详解C++中的抽象类与虚函数表的实现
我们创建了两个派生类,通过输出可以看到a1和a2都输出了自己的名字,而a1调用test输出的是基类test的函数,实现这种现象是因为c++中的虚函数表,虚函数表是一个存储虚函数指针的数组,每个类(含虚函数的类)会生成一个虚函数表,每个对象在内存中会通过一个隐式的。具体情况我们看下面的测试。目前基类使用非虚的析构函数,我们运行后会发现只输出了Base destructor,这肯定是不行的我们的派生类没有运行析构,会导致严重的内存泄露。下面我们来使用一下Abstract这个基类。指向它所属类的虚函数表。
2025-03-11 18:51:52
386
原创 CMake构建cpp代码的实践
是一个跨平台的构建系统生成器,它通过高级的配置文件()生成底层构建工具所需的文件(如 Make的Makefile他的主要作用就是组织cpp代码,生成make的Makefile文件用于编译,它支持多平台(Linux、Windows、macOS)和多编译器(GCC、Clang、MinGW)我们的测试代码是cpp的,下面是我们的目录结构。
2025-03-11 17:15:29
512
原创 Docker 如何创建自己的镜像(多阶段构建) Dockerfile文件的使用
本教程教大家如何使用Dockerfile文件创建自己的镜像,我们使用一个简短的go代码作为演示,它的作用是开启一个http端口,下面是我们的go代码。我们使用多阶段构建的形式来制作镜像,这种方式的好处是使程序运行在一个更稳定的环境中,还可以大大减少镜像的大小,接下来我们逐行解析。输出如上就表示运行成功了,下面我们开始讲解如何使用docker制作一个容器来运行这个代码。拿到代码后要先确保电脑安装了go的环境,如果有我们运行下面的命令,先来运行一下看看效果。
2025-03-10 23:24:44
451
原创 详解Qt信号与槽机制,讲解底层实现
connect的作用是链接信号与槽,连接后Qt 将发送者对象、信号索引、接收者对象、槽函数索引、连接类型等信息存储在一个全局的 **连接列表** 中,还会进行参数校验,槽的参数可以比信号少,在使用时信号与槽支持基本的隐式类型转换(例如 `int` 可隐式转为 `double`),但是不正常自定义的隐式转换,最后通过 `QMetaMethod::methodIndex()` 获取信号和槽在元对象中的唯一索引。若发送者与接收者同线程,使用**直接连接**;否则使用**队列连接**。下面我们帮演示边讲解原理。
2025-03-10 15:45:27
580
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅