当前位置: 首页 > news >正文

成员访问运算符重载(详解)

目录

成员访问运算符

两层结构下的使用

三层结构下的使用(难点)

内存分析


成员访问运算符

成员访问运算符包括箭头访问运算符 -> 和解引用运算符 * ,它们是指针操作最常用的两个运算符。我们先来看箭头运算符 ->

箭头运算符只能以成员函数的形式重载,其返回值必须是一个指针或者重载了箭头运算符的对象。来看下例子:

两层结构下的使用

例子:建立一个双层的结构,MiddleLayer含有一个Data*型的数据成员

image-20231127173105700

image-20231127173356110

栈帧结束,栈帧结束,ml会调用析构函数,会delete _pdata 空间所以 ml 管理的对象至少应该在堆上的空间

Data*原生指针的用法如下,需要关注堆空间资源的回收

Data * p = new Data();
p->getData();
(*p).getData();
delete p;
p = nullptr;

如果用这种方式创建MiddleLayer对象,我们发现不需要手动delet pdata,并没有发生内存泄露,反而手动delet pdata后会有double free的问题

 

因为MiddleLayer对象实际上对堆上Data对象形成了接管。当函数栈帧结束会自动调用析构函数将堆上的空间回收,所以如果再次手动调用delete pdata 会出现double free的问题。

当然,也可以让Middlelayer对象自己管理一个Data对象,这样就不会出现那种情况了。

image-20240314112042932

image-20240314112053390

需求:希望实现一个这样的效果,创建MiddleLayer对象ml,让ml对象可以使用箭头运算符去调用Data类的成员函数getData

MiddleLayer ml(new Data);
cout << ml->getData() << endl;

箭头运算符无法应对MiddleLayer对象,那么可以定义箭头运算符重载函数。

  • 首先不用考虑重载形式,箭头运算符必须以成员函数形式重载;

  • 然后考虑返回类型,返回值需要使用箭头运算符调用getData函数,而原生的用法只有Data* 才能这么用,所以返回值应该是一个Data* ,此时应该直接返回 _pdata;

  • 同时考虑到一个问题:MiddleLayer的数据成员是一个Data*,创建MiddleLayer对象时初始化这个指针,让其指向了堆上的Data对象,那么还应该补充析构函数使MiddleLayer对象销毁时能够回收这片堆上的资源。

Data* operator->(){return _pdata;
}

思考,解引用运算符应该如何重载能够实现同样的效果呢?直接使用MiddleLayer对象模仿Data*指针去访问getData函数

image-20240314113617206

image-20240314113636052

image-20240314113714656

 

当我们完成了以上的需求后,还有一件“神奇”的事情,使用的语句中有new没有delete,但是检查发现并没有内存泄漏

原因:ml本身是一个局部对象,因为重载了箭头运算符和解引用运算符,所以看起来像个指针,也可以像指针一样进行使用,但是这个对象在栈帧结束时会自动销毁,自动调用析构函数回收了它的数据成员所申请的堆空间

实际上,这就是智能指针的雏形:其思想就是通过对象的生命周期来管理资源。

下面为测试代码,可以自行进行测试

#include<iostream>
using namespace std;
class Data {
public ://构造函数Data(){cout << "Data()" << endl;}Data(int x):_data(x){cout << "Data(int)" << endl;}int get()const { return _data; }~Data() { cout << "~Data()" << endl; }
private:int _data = 10;
};class middlelayer {
public:middlelayer(Data* p):_pdata(p){cout << "middlelayer(Data*)" << endl;}~middlelayer() {if (_pdata) {delete _pdata;_pdata = nullptr;}}Data * operator->(){return _pdata;}//要返回一个data对象,才可以用点来Data& operator* (){return *_pdata;}
private:Data* _pdata;
};void test()
{//下面两行代码会出错,因为栈帧结束,ml会调用析构函数,所以ml管理的对象至少应该在堆上的空间/*Data d1;middlelayer ml( &d1);*///不建议这样使用,//因为如果手动的通过p1指针来回收堆上的Data对象空间//会出现double free的问题Data* p1 = new Data();cout << p1->get() << endl;cout << (*p1).get() << endl;middlelayer ml(p1);//delete p1;
}
void test1()
{Data* p1 = new Data();cout << p1->get() << endl;cout << (*p1).get() << endl;delete p1;//智能指针的雏形//利用局部对象的生命周期管理堆上的资源//ml是middlelayer类对象,不是指针//但是可以像原生的data* 指针一样使用箭头运算符和解引用运算符//访问data的成员//并且,不需要像原生的指针一样去手动调用回收堆上的data空阿金middlelayer ml(new Data());//为什么可以进行重载呢,因为middlelayer底层的原型就是data类型cout << ml->get() << endl;//如下是middlelayer使用箭头运算符访问data类成员函数的本质形式//ml对象调用operator->函数,返回值是一个Data*//编译器自动加上了一个->原生的箭头运算符cout << ml.operator->()->get() << endl;cout << (*ml).get() << endl;cout << ml.operator*().get() << endl;//本质形式
}
int main()
{test1();return 0;
}
三层结构下的使用(难点)
  • 拓展思考:那么如果结构再加一层,引入一个ThirdLayer类

创建ThirdLayer对象时注意避免这样的错误

注意:应该让ThirdLayer底层的指针管理一个堆上的MiddleLayer对象

希望实现如下使用方式,思考一下应该如何对ThirdLayer进行对应的运算符重载

ThirdLayer tl(new MiddleLayer(new Data));
cout << tl->getData() << endl;
cout << (*(*tl)).getData() << endl;

在ThirdLayer类中定义这两个成员函数

—— 在使用时就可以这样用

箭头运算符的使用:

解引用运算符的使用:

  • 拓展思考:如果解引用的使用也希望和箭头运算符一样,一步到位,又该如何实现

ThirdLayer tl(new MiddleLayer(new Data));
cout << (*tl).getData() << endl;

如下三种return的形式都可以实现。

内存分析

三层的结构比较复杂,我们可以通过内存图的方式进行分析。

ThirdLayer对象的创建

ThirdLayer tl(new MiddleLayer(new Data));

实际上的内存结构如图

创建和销毁的过程:

创建tl对象时,调用ThirdLayer的构造函数,在ThirdLayer构造函数的参数初始化过程中调用MiddleLayer的构造函数,在ThirdLayer构造函数的参数初始化过程调用Data的构造。

Data构造完才能完成MiddleLayer的指针数据成员初始化,MiddleLayer创建完毕,才能完成ThirdLayer的指针数据成员初始化。

tl销毁时,马上调用ThirdLayer的析构,执行delete _pml时,第一步调用MiddleLayer的析构,在这个过程中,会delete _pdata,会调用Data的析构函数。

由于构造函数打印信息语句只能在函数体中,所以呈现出如下结果

下面为测试代码,可以自行测试

#include<iostream>
using namespace std;
class Data {
public ://构造函数Data(){cout << "Data()" << endl;}Data(int x):_data(x){cout << "Data(int)" << endl;}int get()const { return _data; }~Data() { cout << "~Data()" << endl; }
private:int _data = 10;
};class middlelayer {
public:middlelayer(Data* p):_pdata(p){cout << "middlelayer(Data*)" << endl;}~middlelayer() {cout << "~middlelayer()" << endl;if (_pdata) {delete _pdata;_pdata = nullptr;}}Data * operator->(){return _pdata;}//要返回一个data对象,才可以用点来Data& operator* (){return *_pdata;}friend class thirdlayer;
private:Data* _pdata;
};class thirdlayer {
public:thirdlayer(middlelayer* ml):_pml(ml){cout << "thirdlayer(middlelayer *)" << endl;}~thirdlayer() {cout << "~thirdlayer()" << endl;if (_pml){delete _pml;_pml = nullptr;}}//返回middlelayer对象,因为middlelayer对象对->进行了重载middlelayer& operator ->(){return *_pml;}//1.一步一步解引用/*middlelayer& operator*(){return *_pml;}*///2.一步到位解引用Data& operator*(){//从thirdlayer出发只能得到middlelayer对象//由于middlelayer对象已经对解引用运算符进行了初始化进行过重载//所以可以直接通过对middlelayer对象解引用得到data对象//return *(*_pml);//return (*_pml).operator*();//从内存的角度//_pml存储的是middlelayer,通过middlelayer访问data的地址,但是要将thirdlayer声明为middlelayer的友元类才能访问私有成员return *((*_pml)._pdata);}
private:middlelayer* _pml;
};void test()
{//下面两行代码会出错,因为栈帧结束,ml会调用析构函数,所以ml管理的对象至少应该在堆上的空间/*Data d1;middlelayer ml( &d1);*///不建议这样使用,//因为如果手动的通过p1指针来回收堆上的Data对象空间//会出现double free的问题Data* p1 = new Data();cout << p1->get() << endl;cout << (*p1).get() << endl;middlelayer ml(p1);//delete p1;
}
void test1()
{Data* p1 = new Data();cout << p1->get() << endl;cout << (*p1).get() << endl;delete p1;//智能指针的雏形//利用局部对象的生命周期管理堆上的资源//ml是middlelayer类对象,不是指针//但是可以像原生的data* 指针一样使用箭头运算符和解引用运算符//访问data的成员//并且,不需要像原生的指针一样去手动调用回收堆上的data空阿金middlelayer ml(new Data());//为什么可以进行重载呢,因为middlelayer底层的原型就是data类型cout << ml->get() << endl;//如下是middlelayer使用箭头运算符访问data类成员函数的本质形式//ml对象调用operator->函数,返回值是一个Data*//编译器自动加上了一个->(原生的箭头运算符)cout << ml.operator->()->get() << endl;cout << (*ml).get() << endl;cout << ml.operator*().get() << endl;//本质形式//是不可以的,和上面原因是一样的,因为tl是指向在栈上的空间,但是函数栈帧销毁的时候会调用delete,会出现错误//thirdlayer tl(&ml);}void test2()
{//调用tl的构造函数在调用middlelayer的构造函数在调用Data的构造函数,当data构造完成,后middlelayer构造完成,tl才能构造完成//就和递归很像thirdlayer tl(new middlelayer(new Data()));//tl调用operator->函数,返回值是其管理的middlelayer对象//由于middlelayer类中已经有对->运算符进行了重载//所以middlelayer对象可以直接使用->运算符访问data类中的成员//本质上就是调用了middlelayer的operator->函数cout << (tl.operator->()).operator->()->get() << endl;cout << (tl.operator->())->get() << endl;cout << tl->get() << endl;//1.一步一步解引用//因为middlelayer类已经对*运算符进行了重载//所以对third对象解引用只需要得到一个middlelayer对象/*cout << ((tl.operator*()).operator*()).get() << endl;cout << (*(*tl)).get() << endl;cout << (*(tl.operator*())).get() << endl;*///2.一步解引用cout << (*tl).get() << endl;cout << (tl.operator*()).get() << endl;
}
int main()
{test2();return 0;
}

相关文章:

成员访问运算符重载(详解)

目录 成员访问运算符 两层结构下的使用 三层结构下的使用&#xff08;难点&#xff09; 内存分析 成员访问运算符 成员访问运算符包括箭头访问运算符 -> 和解引用运算符 * &#xff0c;它们是指针操作最常用的两个运算符。我们先来看箭头运算符 -> 箭头运算符只能以…...

无感改造,完美监控:Docker 多阶段构建 Go 应用无侵入观测

作者&#xff1a;牧思 背景 随着云原生的普及&#xff0c;Golang 编程语言变得越来越热门。相比 Java&#xff0c;Golang 凭借其轻量&#xff0c;易学习的特点得到了越来越多工程师的青睐&#xff0c;然而由于 Golang 应用需要被编译成二进制文件再进行运行&#xff0c;Golan…...

项目后期发现重大漏洞,如何紧急修复

项目后期发现重大漏洞的紧急修复关键在于&#xff1a; 迅速识别漏洞根本原因、制定修复优先级、协调团队资源、实施快速修复和验证、总结经验防止重复发生。 其中&#xff0c;迅速识别漏洞根本原因是最为关键的一步。找到漏洞的根本原因有助于确保修复措施不仅解决眼前的问题&a…...

设计模式:状态模式 - 复杂状态切换的优雅之道

一、为什么用状态模式&#xff1f; 在开发过程中&#xff0c;你是否遇到过这样的难题&#xff1a;对象需要根据不同的状态执行不同行为&#xff0c;但代码中却充斥着大量的if-else或switch-case语句&#xff1f; 随着状态的增多&#xff0c;代码变得臃肿且难以阅读&#xff0…...

【AI提示词】业务开发经理

提示说明 业务开发经理旨在帮助用户构建一个高效、有洞察力的业务发展角色&#xff0c;能够在竞争激烈的市场中寻找并抓住商机。 提示词 # 角色 业务开发经理专家## 注意 - 业务开发经理应具备强烈的市场洞察力和人际沟通能力。 - 专家设计应考虑业务发展的实际需求和挑战。…...

发电机参数详解

一、发电机参数体系概述 发电机作为将机械能转换为电能的核心设备,其参数体系涵盖电气、机械、结构、性能、控制五大维度,是设备选型、运行维护、故障诊断的重要依据。参数体系的完整性和准确性直接影响电力系统的稳定性与经济性。以下通过思维导图展示发电机参数的整体架构…...

每天五分钟深度学习PyTorch:RNN CELL模型原理以及搭建

本文重点 RNN Cell(循环神经网络单元)是循环神经网络(RNN)的核心组成部分,用于处理序列数据中的每个时间步,并维护隐藏状态以捕获序列中的时间依赖关系。 RNN CELL的结构 RNN是一个循环结构,它可以看作是RNN CELL的循环,RNN CELL的结构如下图所示,RNN CELL不断进行…...

设计和实现一个基于 DDS(直接数字频率合成) 的波形发生器

设计和实现一个基于 DDS&#xff08;直接数字频率合成&#xff09; 的波形发生器 1. 学习和理解IP软核和DDS 关于 IP 核的使用方法 IP 核&#xff1a;在 FPGA 设计中&#xff0c;IP 核&#xff08;Intellectual Property Core&#xff09;是由硬件描述语言&#xff08;HDL&a…...

RCEP框架下eBay日本站选品战略重构:五维解析关税红利机遇

2024年RCEP深化实施背景下&#xff0c;亚太跨境电商生态迎来结构性变革。作为协定核心成员的日本市场&#xff0c;其跨境电商平台正经历新一轮价值重构。本文将聚焦eBay日本站&#xff0c;从政策解读到实操路径&#xff0c;系统拆解跨境卖家的战略机遇。 一、关税递减机制下的…...

使用 Node.js、Express 和 React 构建强大的 API

了解如何使用 Node.js、Express 和 React 创建一个强大且动态的 API。这个综合指南将引导你从设置开发环境开始&#xff0c;到集成 React 前端&#xff0c;并利用 APIPost 进行高效的 API 测试。无论你是初学者还是经验丰富的开发者&#xff0c;这篇文章都适合你。 今天&#…...

如何争取高层对项目的支持

争取高层对项目的支持关键在于明确项目的战略价值、展示其可行性与回报、以及有效的沟通和利益对接。高层管理者通常关注的是项目如何帮助公司实现整体战略目标&#xff0c;如何提高企业的竞争力或收益。在争取支持的过程中&#xff0c;项目经理需要清楚地表达项目的潜在价值&a…...

git合并分支原理

Git合并的原理是基于三方合并&#xff08;three-way merge&#xff09;算法&#xff0c;它通过比较三个快照来合并不同分支上的更改。这三个快照包括两个要合并的分支的最新提交和它们的共同祖先提交。合并过程并不是简单地按照提交时间来进行&#xff0c;而是通过比较这些快照…...

最短路问题

最短路问题 最短路问题 最短路算法&#xff08;Shortest Path Algorithm&#xff09;是用来解决图中两点之间的最短路径的问题。常见的应用包括&#xff1a;地图导航、网络路由、游戏寻路等。根据图的性质&#xff08;有向/无向、是否有负权边&#xff09;和需求&#xff08;…...

ARM Cortex汇编伪指令

在ARM架构&#xff08;尤其是Cortex-M系列MCU&#xff09;的汇编中&#xff0c;伪指令&#xff08;Pseudo-Instructions&#xff09;是由汇编器解释的特殊指令&#xff0c;用于定义数据、符号、代码结构或控制汇编过程。以下是常用的ARM汇编伪指令分类及说明&#xff1a; 一、…...

如何在vue3项目中使用 AbortController取消axios请求

在 Vue3 项目中通过 AbortController 取消 Axios 请求&#xff0c;可以通过以下 结构化步骤 实现。我们结合组合式 API&#xff08;Composition API&#xff09;和现代前端实践演示&#xff1a; 一、基础实现&#xff08;单个请求&#xff09; 1. 创建组件逻辑 <script s…...

Bright+Data网页解锁器在旅游行业的创新实践

引言 随着在线旅游平台的快速发展&#xff0c;网络爬虫技术成为获取旅游数据的重要手段。然而&#xff0c;主流旅游网站&#xff08;如去哪儿网、携程等&#xff09;普遍部署了反爬虫机制&#xff0c;包括IP封禁、验证码验证、请求频率限制等技术手段&#xff0c;严重影响了传…...

SpringMVC 执行流程

前言&#xff1a; 在前后端分离的情况下&#xff0c;SpringMVC 的执行流程主要集中在处理 RESTful 请求和返回 JSON 数据。这里的 Controller 会直接返回数据&#xff0c;而不是视图。我们通常会使用 RestController 和 RequestMapping 来处理请求&#xff0c;ResponseBody 会…...

STM32G0单片机自带RTC

STM32有个自带RTC外设&#xff0c;外接32.768KHz的晶振后可得到相对精确的计时功能。 实测了一个一小时快个1秒多。 1 cubeMX设置了RTC后自动生成的初始化代码如下 static void MX_RTC_Init(void) {/* USER CODE BEGIN RTC_Init 0 *//* USER CODE END RTC_Init 0 */RTC_TimeT…...

Linux(9)Apache

文章目录 Apache1&#xff09;概述2&#xff09;部署方案3&#xff09;yum安装Apache3.1、安装Apache3.2、启动Apache3.4、检查服务是否启动成功3.5、创建一个html页面3.6、yum安装Apache相关配置文件 4&#xff09;源码安装Apache4.1、源码编译口诀4.2、安装Apache4.2.1、获取…...

用DeepSeek AI高效制作专业PPT

在当今职场中,制作精美而有力的PPT是展示想法、汇报工作和赢得机会的关键技能。然而,许多人花费过多时间在格式调整和内容组织上,而非专注于核心信息的传达。DeepSeek AI作为新一代智能助手,能够帮助您将PPT制作效率提升300%,同时显著提高专业度。本文将详细介绍如何利用D…...

C++红黑树

目录 一、红黑树的概念 二、红黑树的定义 三、红黑树的实现 一、红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或者Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#…...

Day08 【基于jieba分词实现词嵌入的文本多分类】

基于jieba分词的文本多分类 目标数据准备参数配置数据处理模型构建主程序测试与评估测试结果 目标 本文基于给定的词表&#xff0c;将输入的文本基于jieba分词分割为若干个词&#xff0c;然后将词基于词表进行初步编码&#xff0c;之后经过网络层&#xff0c;输出在已知类别标…...

宝塔面板中解锁Laravel日志查看的奥秘

目录 一、前言二、Laravel 日志基础认知2.1 日志的作用2.2 Laravel 日志的默认配置 三、查找 Laravel 日志文件位置3.1 常规存储路径3.2 自定义路径查找 四、查看 Laravel 日志内容4.1 宝塔面板文件管理器查看4.2 使用命令行查看 五、常见问题及解决方法5.1 权限不足无法查看5.…...

基于MCP协议的多模态思维链在医疗系统改造中的融合研究

一、结构优化与内容整合编程方案 1. 强化MCP协议的技术映射 技术实现:上下文关联与动态资源适配 代码方案:基于Spring Cloud + OpenTelemetry的MCP协议集成 // MCP协议全局Trace ID生成与传递(Java示例) @Configuration public class MCPTraceConfig {@Beanpublic SpanP…...

js原型链污染

JavaScript 是一门非常灵活的语言&#xff0c;与 PHP 相比起来更加灵活。除了传统的 SQL 注入、代码执行等注入型漏洞外&#xff0c;也会有一些独有的安全问题&#xff0c;比如今天要说这个原型链污染。本篇文章就让我们来学习一下 NodeJS 原型链与原型链污染的原理。 什么是原…...

【HDFS入门】HDFS核心组件Failover Controller:高可用保障机制解析

目录 1 Failover Controller的角色职责 2 Failover Controller的运行原理 2.1 核心组件依赖 2.2 高可用架构图 3 故障转移机制详解 3.1 正常状态下的工作流程 3.2 故障触发切换流程 4 关键机制与技术挑战 4.1 防止脑裂&#xff08;Fencing&#xff09; 4.2 元数据同步 4.3 ZKFC…...

A008-Web 功能测试 – 咪咕音乐UI自动化,selenium

测试网址&#xff1a; https://music.migu.cn/v3 注 1&#xff1a;请设置足够的睡眠时间&#xff0c;保证网页顺利打开 注2&#xff1a;打开页面过程中&#xff0c; 网站可能有弹窗、验证信息&#xff0c;如果有&#xff0c;请手动关闭或重新运行代码&#xff0c; 保证后续流…...

Go:使用共享变量实现并发

竞态 在串行程序中&#xff0c;步骤执行顺序由程序逻辑决定&#xff1b;而在有多个 goroutine 的并发程序中&#xff0c;不同 goroutine 的事件先后顺序不确定&#xff0c;若无法确定两个事件先后&#xff0c;它们就是并发的。若一个函数在并发调用时能正确工作&#xff0c;称…...

私域流量运营:如何高效处理海量社群订单?

电商行业进入存量竞争时代&#xff0c;私域流量正悄然改写商业规则。这个被企业主们频频提及的概念&#xff0c;本质上是在构建自主可控的用户资产池——就像知名茶饮品牌「喜茶」通过会员系统沉淀3000万粉丝&#xff0c;实现复购率提升35%的数字化转型。当企业微信对话框、社群…...

【TI MSPM0】ADC进阶学习

一、学习内容 二、ADC配置讲解 转换时钟来源于本地的80mhz的振荡器&#xff0c;使得高速的12bits的转换可以达到4mhz的采样率 ADC转换过程分两个步骤&#xff0c;一是采样&#xff0c;二是转换 因此&#xff0c;配置中的是采样时钟 真正决定采样速率的是conversion clock 决定…...

一文读懂WPF系列之MVVM

WPF MVVM 什么是MVVMWPF为何使用MVVM机制WPFMVVM 的实现手段 INotifyPropertyChanged​数据绑定的源端通知​​原理 PropertyChanged事件双向绑定的完整条件常见疑惑问题 什么是MVVM 翻译全称就是 model-view-viewmodel 3部分内容 以wpf的概念角度来解释就是 数据库数据源模型…...

WPF静态资源StaticResource和动态资源DynamicResource有什么区别,x:Static又是什么意思?

什么叫WPF的资源(Resource) 资源是保存在可执行文件中的一种不可执行数据。WPF中资源用ResourceDictionary类表示&#xff0c;这个类就是一个字典&#xff0c;字典的key和value都是object类型。所以在WPF中&#xff0c;资源可以可以是图像、字符串等所有的任意CLR对象&#xf…...

vue3环境搭建、nodejs22.x安装、yarn 1全局安装、npm切换yarn 1、yarn 1 切换npm

vue3环境搭建 node.js 安装 验证nodejs是否安装成功 # 检测node.js 是否安装成功----cmd命令提示符中执行 node -v npm -v 设置全局安装包保存路径、全局装包缓存路径 在node.js 安装路径下 创建 node_global 和 node_cache # 设置npm全局安装包保存路径&#xff08;新版本…...

配置HADOOP_HOME环境变量和maven_HOME环境变量

1.右击此电脑&#xff0c;选择“属性” 2.选择“高级系统配置” 3.选择“环境变量” 4.在“系统变量”下新建两个系统变量 注意&#xff1a;变量值要“浏览目录”选择你存放hadoop的文件和maven的文件 5.在“系统变量”里双击Path”&#xff0c;在里面新建两个变量...

计算机网络:实验五路由器的应用

实验五路由器的应用 1.1实验目的 掌握路由器的应用&#xff1b;熟悉路由器的基本配置方法。 1.2实验要求 学生提前准备好实验报告&#xff0c;预习并熟悉实验步骤&#xff1b;遵守实验室纪律&#xff0c;在规定的时冋内完成要求的内容。 1.3 实验内容与步骤 1、假设企业网…...

【正点原子STM32MP257连载】第四章 ATK-DLMP257B功能测试——RS232接口测试

1&#xff09;实验平台&#xff1a;正点原子ATK-DLMP257B开发板 2&#xff09;浏览产品&#xff1a;www.alientek.com 3&#xff09;全套实验源码手册视频下载&#xff1a;正点原子资料下载中心 文章目录 第四章 ATK-DLMP257B功能测试——RS232接口测试 第四章 ATK-DLMP257B功能…...

考研单词笔记 2025.04.15

addition n添加&#xff0c;增加&#xff0c;加法 additional a附加的&#xff0c;额外的 in addition 另外&#xff1b;除此之外&#xff1b;加之 augment v增加&#xff0c;增强&#xff0c;提高 explode v急剧增长&#xff0c;爆炸&#xff0c;爆发&#xff0c;迸发 gr…...

zkmall模块商城:B2C 场景下 Vue3 前端性能优化的广度探索与实践

ZKmall作为面向B2C场景的模块化电商平台&#xff0c;其前端性能优化在Vue3框架下的实践融合了架构设计、渲染机制与业务特性&#xff0c;形成了一套多维度的优化体系。以下从技术实现与业务适配两个维度展开分析&#xff1a; 一、Vue3响应式系统深度适配 ​Proxy驱动的精准更新…...

WebSocket 技术详解

引言 在现代Web应用中&#xff0c;实时通信已经成为不可或缺的一部分。想象一下聊天应用、在线游戏、股票交易平台或协作工具&#xff0c;这些应用都需要服务器能够即时将更新推送给客户端&#xff0c;而不仅仅是等待客户端请求。WebSocket技术应运而生&#xff0c;它提供了一…...

微服务即时通信系统---(四)框架学习

目录 ElasticSearch 介绍 安装 安装kibana ES客户端安装 头文件包含和编译时链接库 ES核心概念 索引(Index) 类型(Type) 字段(Field) 映射(mapping) 文档(document) ES对比MySQL Kibana访问ES测试 创建索引库 新增数据 查看并搜索数据 删除索引 ES…...

日常记录-CentOS 9安装java17

文章目录 前言一、手动安装 Oracle JDK 17 或 OpenJDK 17&#xff08;适合自定义路径&#xff09;二、使用 CentOS 9 系统包安装 OpenJDK 17&#xff08;简单稳定&#xff09;三、使用 SDKMAN&#xff08;管理多个版本&#xff09;总结 前言 CentOS 9安装java17 一、手动安装 …...

Python 导出 PDF(ReportLab )

文章目录 1. ReportLab 使用1.1. 安装 ReportLab1.2. 创建 PDF 文件1.3. 使用文档模板 DocTemplate1.4. 使用页面模板 PageTemplate1.5. 继承 BaseDocTemplate1.6. 使用 SimpleDocTemplate1.7. 继承Canvas1.8. 直接使用Canvas 2. 字体与编码3. PLATYPUS - 页面布局和排版3.1. 设…...

私域运营的底层逻辑:从流量到留存的进阶之路

私域流量已成为企业营销的新战场&#xff0c;但盲目跟风只会事倍功半。 接下来&#xff0c;我将深入剖析私域运营的底层逻辑&#xff0c;从几个关键环节&#xff0c;助你构建高效稳定的私域体系。 一、价值优先&#xff1a;以用户需求为核心 私域运营并非简单的粉丝积累&…...

【数据结构 · 初阶】- 带头双向循环链表

目录 1.尾插 2.初始化 3.尾删、头插、头删 4.查找&#xff0c;返回 pos 指针 5.pos 前插入 优化头插&#xff0c;直接复用 优化尾插&#xff0c;直接复用 6.pos 位删除 头删尾删简化 7.销毁 整体代码 List.h List.c Test.c 循环&#xff1a;1.尾 next 指向哨兵位…...

Cube IDE常用快捷键

STM32CubeIDE常用快捷键 STM32CubeIDE快捷键很多&#xff0c;可以通过 Help > Show Active Keybindings… 查看当前可用快捷键&#xff1b;也可以在 Window > Preferences > General > Keys 中查看修改快捷键 快捷键快捷键说明Ctrl/注释行/取消注释行CtrlD删除行…...

C++开发中的DUMP文件:解决崩溃与性能问题的利器(全文字数2w+)

[外链图片转存中…(img-mf6LznjF-1744717065188)] 文章目录 前言为什么需要了解DUMPDUMP在C开发中的重要性 一、DUMP基础概念1. 什么是DUMP文件2. DUMP文件的类型3. DUMP文件的作用&#xff08;1&#xff09;调试程序崩溃&#xff08;2&#xff09;分析程序性能&#xff08;3&a…...

Golang|接口并发测试和压力测试

文章目录 这里出现某些奖品和数据库中库存量不一致的问题原因就是在并发的情况下&#xff0c;sync.Map仍然会出现脏写问题&#xff0c;就是在同时操作下的操作覆盖问题可以先把数据放到channel里&#xff0c;然后用一个单一的协程负责读取channel并写入map...

解决 Maven 500 错误:无法传输 maven-metadata.xml 文件

在使用 Maven 构建和管理 Java 项目时&#xff0c;可能会遇到类似以下的错误信息&#xff1a; [WARNING] Could not transfer metadata com.ha:xxx-model:2025.0.1.SNAPSHOT/maven-metadata.xml from/to public (http://xxx.xx.xx.xx/repository/maven-public): status code: …...

鸿蒙应用开发—鸿蒙app一键安装脚本

背景 当鸿蒙App开发完后需要提测&#xff0c;如何将App文件发给QA安装测试&#xff0c;是一件麻烦事&#xff0c;因为鸿蒙App并不能像Android Apk那样可以直接安装到设备中&#xff0c;能想到的方式有&#xff1a; 直接叫测试拿手机过来安装让测试安装DevEco Studio 拉代码编…...

opencv二值化实验

二值化实验 1二值化说明2 阈值法&#xff08;THRESH_BINARY&#xff09;3.反阈值法&#xff08;THRESH_BINARY_INV&#xff09;4截断阈值法&#xff08;THRESH_TRUNC&#xff09;5 低阈值零处理&#xff08;THRESH_TOZERO&#xff09;6 超阈值零处理&#xff08;THRESH_TOZERO_…...