C语言向C++过渡的基础知识(二)

目录

C++中的函数重载

函数重载介绍

函数类型的使用

C++中的引用

引用的介绍

引用的使用

引用与指针的对比

常量引用

引用在实际中的使用

函数返回值

返回值和返回引用时间消耗对比

函数形式参数

形式参数为值与形式参数为引用时间消耗对比

内联函数

内联函数的特点


C++中的函数重载

函数重载介绍

在C语言中,不能出现名字相同的函数,因为C语言中的编译过程函数是通过函数名以及对应的地址来找到函数并调用的,如果名字相同,那么编译器将无法分辨是哪一个函数

在C++中,允许在同一作用域下使用相同的函数名配合参数不同、参数类型和不同参数类型的不同顺序构成函数重载

//参数类型不同的重载
//整型参数
int add(int a, int b)
{return a + b;
}
//浮点型参数
double add(double a, double b)
{return a + b;
}//参数个数不同的重载
//两个参数
int add(int a, int b)
{return a + b;
}
//三个参数
int add(int a, int b, int c)
{return a + b + c;
}//不同类型的但数量相同情况下的不同参数顺序的重载
//注意变量名不需要更改顺序
//int类型在前,char类型在后
int getcharacter(int a, char b)
{return b;
}
//char类型在前,int类型在后
int getcharacter(char a, int b)
{return a;
}

📌

注意返回类型不可以作为判断函数是否重载的条件,函数重载只有三种特点:

  1. 参数个数不同
  2. 参数类型不同
  3. 相同个数相互类型不同情况下,不同的参数顺序

函数重载一般用于针对不同类型实现相同的功能,例如

//函数重载
//针对整型的加法函数
int add(int a, int b)
{return a + b;
}//针对浮点型的加法函数
double add(double a, double b)
{return a + b;
}

函数类型的使用

在没有进入类之前,对于全局域的函数重载来说,正常调用对应函数名,但是需要传递正确的实参,例如

//整型加法
int add(int a, int b)
{return a + b;
}
//浮点型加法
double add(double a, double b)
{return a + b;
}
#include <iostream>
using namespace std;int main()
{    //传哪种类型值就调用哪种类型的函数cout <<"整型加法:" << add(1, 2) << endl;cout <<"浮点型加法:"<< add(1.1, 2.2) << endl;return 0;
}
输出结果:
整型加法:3
浮点型加法:3.3

如果使用命名空间,则需要满足需要重载的函数在同一个命名空间,并且使用域作用限定符调用函数,传递实参时依旧是满足传哪种类型的值就调用哪种类型的函数

注意,含有缺省参数的函数和无缺省参数的函数无法构成函数重载,例如

//缺省参数与函数重载
int add(int a = 10, int b = 20)
{return a + b;
}int add(int a, int b = 30)
{return a + b;
}
//将会报错为add函数重定义

📢

了解:

C++是通过函数名修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载

例如在Linux平台下用g++编译的函数重载后的函数名为_Z3addii(对应两个int类型参数的add函数),_Z3adddd(对应两个double类型参数的add函数),两个函数名中的3为函数本身(不包括类型)的名字长度,例如add函数名字是3个字符的长度

C++中的引用

引用的介绍

在C语言中,为了可以通过其他变量直接改变某一个变量的值由此引出了指针的概念,通过指针类型可以改变该指针指向的空间的内容

在C++中,使用引用来辅助指针的使用,例如:

📌

注意引用的底层依旧是指针实现

//指针中的swap函数
void swap(int* num1, int* num2)
{int tmp = *num1;*num1 = *num2;*num2 = tmp;
}//使用引用的函数
void swap(int& num1, int& num2)
{int tmp = num1;num1 = num2;num2 = tmp;
}#include <iostream>
using namespace std;int main()
{//C语言中的swap函数int a = 1;int b = 0;cout << "指针交换" << endl;cout << "交换前:" << endl;cout << a << " " << b << endl;swap(&a, &b);cout << "交换后:" << endl;cout << a << " " << b << endl;//C++中使用引用的swap函数a = 1;b = 0;cout << endl;cout << "引用交换" << endl;cout << "交换前:" << endl;cout << a << " " << b << endl;swap(a, b);cout << "交换后:" << endl;cout << a << " " << b << endl;return 0;
}
输出结果:
指针交换
交换前:
1 0
交换后:
0 1引用交换
交换前:
1 0
交换后:
0 1

在C++中,引用相当于为变量取一个别名(引用变量),这个别名和其对应的变量(引用实体)共用一个地址,所以可以通过引用直接改变对应的变量所在空间的内容

所以在上面的代码中,对于引用变量的函数void swap(int& num1, int& num2)num1num2为实参ab的别名,所以此时num1num2ab的地址相同,直接在swap函数改变num1num2的值即可改变实参ab中的值

引用的使用

在C++中,使用下面的语法创建引用变量

引用实体的类型 &引用变量名 = 引用实体;

📌

此处的引用实体可以是任何类型,包括指针类型以及引用类型

//引用与指针
#include <iostream>
using namespace std;int main()
{int a = 0;//指针类型int* p = &a;cout << "指针修改前:" << endl;cout << a << endl;*p = 1;cout << "修改后:" << endl;cout << a << endl;//引用类型a = 0;int& rp = a;cout << "引用修改前:" << endl;cout << a << endl;rp = 1;cout << "修改后:" << endl;cout << a << endl;//引用实体为指针类型a = 0;int*& rpp = p;cout << "引用类型为指针修改前:" << endl;cout << a << endl;*rpp = 1;cout << "修改后:" << endl;cout << a << endl;//引用变量作为引用实体a = 0;int& r = rp;cout << "引用类型为引用变量修改前:" << endl;cout << a << endl;rp = 1;cout << "修改后:" << endl;cout << a << endl;return 0;
}
输出结果:
指针修改前:
0
修改后:
1
引用修改前:
0
修改后:
1
引用类型为指针修改前:
0
修改后:
1
引用类型为引用变量修改前:
0
修改后:
1

引用与指针的对比

在C++中,引用有以下的特点:

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,就不能再引用其他实体(即不可以更改实体)
  4. 没有NULL引用
  5. 使用sizeof关键字计算某个引用的大小时,计算的是引用实体的类型大小,而不是一个固定值
  6. 引用变量自加1相当于对应实体内容加1
  7. 引用没有多级引用,即没有二级及以上引用
  8. 引用在访问指向的实体时不需要解引用,由编译器处理,除非实体是指针类型
  9. 引用在概念上没有实际地址

对比指针的特点:

  1. 指针在使用之前可以不初始化,但是在VS上面必须初始化
  2. 一个变量可以有多个指针
  3. 一个指针指向一个变量时,可以改变其指向,使其指向下一个变量
  4. NULL指针
  5. 使用sizeof关键字计算某个指针的大小时,计算的是指针变量的大小,是一个固定值,在32位机上值为4,在64位机上是8
  6. 指针变量自加1相当于跳过指向的类型占用的内存大小个字节
  7. 指针存在二级及以上的引用
  8. 指针不论指向的类型如何,都必须显式解引用
  9. 指针在概念上和实际上都有自己的实际地址
//指针可以更改指向,引用不可以
#include <iostream>
using namespace std;int main()
{int a = 0;//两个引用指向同一个变量a//变量a给引用变量bint& b = a;cout << "初始a中的值:" << a << endl;//通过引用b改变a的值b = 20;cout << "通过引用改变a中的值:" << a << endl;//改变引用a实体的引用变量b使其指向ccout << "初始a中的值:" << a << endl;int c = 10;cout << "初始c中的值" << c << endl;b = c;cout << "现在a中的值:" << a << endl;//通过引用b改变c的值b = 30;cout << "当前c中的值" << c << endl;cout << "当前a中的值:" << a << endl;return 0;
}
输出结果:
初始a中的值:0
通过引用改变a中的值:20
初始a中的值:20
初始c中的值10
现在a中的值:10
当前c中的值10
当前a中的值:30
//从上面的结果中可以看到,尽管b引用显式得改变了指向,使其指向c,但是实际上只是将c中的值给了b引用,而因为引用b的指向不可以改变,故依旧改变的是a中的值//sizeof
#include <iostream>
using namespace std;int main()
{//一个变量可以有多个引用和指针int a = 0;//两个引用指向同一个变量aint& r = a;//两个指针指向同一个变量aint* p = &a;int*& r2 = p;cout << "计算引用变量大小:(引用int类型)" << sizeof(r) << endl;cout << "计算引用变量大小:(引用int*类型)" << sizeof(r2) << endl;cout << "计算引用指针大小:(64位机,指向int类型)" << sizeof(p) << endl;return 0;
}
输出结果:
计算引用变量大小:(引用int类型)4
计算引用变量大小:(引用int*类型)8
计算引用指针大小:(64位机,指向int类型)8//引用变量和指针+1操作
#include <iostream>
using namespace std;int main()
{int arr[4] = { 1,2,3,4 };int& a1= arr[0];int* a2 = &arr[0];//const int*& a4 = &arr[0];//无法初始化cout << "计算引用实体类型为int类型+1跳过的大小" << endl;cout << "开始位置:" << &arr[0] << " " << "对应数值:" << arr[0] << endl;cout << "结束位置对应数值:" << a1 + 1 << endl;cout << "计算指针+1跳过的大小" << endl;cout << "开始位置:" << &arr[0] << " " << "对应数值:" << arr[0] << endl;cout << "结束位置:" << a2 + 1 << endl;cout << "计算引用实体类型为int*类型+1跳过的大小" << endl;a2 = arr;int*& a3 = a2;const int*& a4 = &arr[0];//注意不可以使用这种写法,因为当前编译器不知道到底右侧值是否可以修改cout << "开始位置:" << &arr[0] << " " << "对应数值:" << arr[0] << endl;cout << "结束位置:" << a3 + 1 << endl;return 0;
}
输出结果:
计算引用实体类型为int类型+1跳过的大小
开始位置:000000970C4FF7B8 对应数值:1
结束位置对应数值:2
计算指针+1跳过的大小
开始位置:000000970C4FF7B8 对应数值:1
结束位置:000000970C4FF7BC
计算引用实体类型为int*类型+1跳过的大小
开始位置:000000970C4FF7B8 对应数值:1
结束位置:000000970C4FF7BC//引用本身的地址和指针本身的地址
#include <iostream>
using namespace std;int main()
{//一个变量可以有多个引用和指针int a = 0;//两个引用指向同一个变量aint& r = a;//两个指针指向同一个变量aint* p = &a;int*& r2 = p;cout << "引用实体为int类型变量的地址:" << &r << endl;cout << "引用实体为int*类型变量的地址" << &r2 << endl;cout << "指针变量指向的int类型变量的地址" << p << endl;cout << "指针变量自身的地址" << &p << endl;return 0;
}
输出结果:
引用实体为int类型变量的地址:0000000C97EFF5A4
引用实体为int*类型变量的地址0000000C97EFF608
指针变量指向的int类型变量的地址0000000C97EFF5A4
指针变量自身的地址0000000C97EFF608

常量引用

在C语言中,可以使用const指针修饰指针变量,并且const可以修饰指针变量整体使得无法通过解引用该指针修改指向空间的内容,也可以放在变量名前方限制指针无法指向其他对象

在C++中,也存在const修饰的引用,但是const只能放在引用变量整体的前面,即const int& a,例如

💡

在指针/引用中,指针和引用的权限只可以缩小不可以放大

//常量引用
#include <iostream>
using namespace std;int main()
{//对于常量来说,需要使用常量引用变量才能引用常量实体const int a = 0;const int& a1 = a;const int& a2 = 10;//10为常量值double d = 2.34;//int& a3 = d;//无法编译,但不是类型不同的原因const int& a3 = d;//可以编译//const int* p = d;//但是指针无法做到同样的实现,原因是类型不同return 0;
}

💡

在强制类型转换的过程中,实际上是创建了一个临时变量,例如

double b = 2.34;

int a = (int)b;

在此处的强制转换过程中,a被赋值为强制转换为int类型的b,但是b本身的值并没有改变,b中存储的值依旧是2.34,但是a中存的值为2,所以强制转换过程中不会直接对需要强制转换的对象b进行改变,而是取出该变量b中的数据放到临时变量中并转换为对应类型再给目标对象a

此时可以解释为什么上面的引用需要加const才可以编译通过

在上面的代码中ddouble类型的变量,而需要强制转换为int类型的变量给int类型的引用,但是在强制转换过程中,是先创建了临时变量存储的d中的值,而临时变量中的值为常量值不可以被改变,所以需要给int类型的引用加const才可以成功编译

引用在实际中的使用

函数返回值

//返回值
int add(int a, int b)
{static int z = a + b;return z;
}#include <iostream>
using namespace std;int main()
{int ret = add(1, 2);cout << ret << endl;return 0;
}
输出结果:
3//返回引用
int& add(int a, int b)
{static int z = a + b;return z;
}#include <iostream>
using namespace std;int main()
{int ret = add(1, 2);cout << ret << endl;return 0;
}
输出结果:
3

在上面的代码中,add函数中有一个static类型的变量,直接返回值时,需要将该变量的值存入寄存器中,再由寄存器带回给add函数被ret接收,而使用引用返回该类型的变量可以在一定程度上减少前面的步骤消耗

但是,注意下面的代码可能会出现问题

#include <iostream>
using namespace std;int& add(int a, int b)
{int z = a + b;return z;
}int main()
{int& ret = add(1, 2);//int ret = add(1, 2);//依旧会有问题cout << ret << endl;cout << "输出结果:" << ret << endl;return 0;
}
输出结果:
3
输出结果:-858993460
//编译器警告:返回局部变量或临时变量的地址: z

因为zadd函数中的局部变量,出了add函数将会被销毁,此时返回z是返回变量z的引用,被ret接收后,ret指向z的位置,当z销毁后,ret依旧指向该位置,但是该位置的值已经不一定是刚才计算出来的结果,因为add函数栈帧空间可能会被覆盖,没被覆盖时该地址的值依旧是计算出来的值,否则就是随机值,具体取决于编译器如何分配空间

📌

在使用引用作为函数返回值时,注意引用的实体尽量不是临时变量或者局部变量,除非返回作为形式参数的引用变量

所以,如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统了,则必须使用传值返回

返回值和返回引用时间消耗对比
#include <iostream>
using namespace std;#include <time.h>
struct A { int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A& TestFunc2() { return a; }
void TestReturnByRefOrValue()
{// 以值作为函数的返回值类型size_t begin1 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc1();size_t end1 = clock();// 以引用作为函数的返回值类型size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2();size_t end2 = clock();// 计算两个函数运算完成之后的时间cout << "TestFunc1 time:" << end1 - begin1 << endl;cout << "TestFunc2 time:" << end2 - begin2 << endl;
}int main()
{TestReturnByRefOrValue();return 0;
}
输出结果:
TestFunc1 time:161
TestFunc2 time:1

函数形式参数

#include <iostream>
using namespace std;void swap(int& num1, int& num2)
{int tmp = num1;num1 = num2;num2 = tmp;
}int main()
{int a = 1;int b = 0;cout << "交换前的a和b:" << "a = " << a << " " << "b = " << b << endl;swap(a, b);cout << "交换后的a和b:" << "a = " << a << " " << "b = " << b << endl;return 0;
}
输出结果:
交换前的a和b:a = 1 b = 0
交换后的a和b:a = 0 b = 1
形式参数为值与形式参数为引用时间消耗对比
#include <iostream>
using namespace std;
#include <time.h>
struct A { int a[10000]; };
void TestFunc1(A a) {}
void TestFunc2(A& a) {}
void TestRefAndValue()
{A a;// 以值作为函数参数size_t begin1 = clock();for (size_t i = 0; i < 10000; ++i)TestFunc1(a);size_t end1 = clock();// 以引用作为函数参数size_t begin2 = clock();for (size_t i = 0; i < 10000; ++i)TestFunc2(a);size_t end2 = clock();// 分别计算两个函数运行结束后的时间cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}int main()
{TestRefAndValue();return 0;
}
输出结果:
TestFunc1(A)-time:15
TestFunc2(A&)-time:0

内联函数

在C语言中,常量和宏函数一般用#define来定义,优点是:增强代码的复用性以及提高性能,但是#define定义的二者在预处理时将会替换其在函数出现的位置,从而导致下面的三个重要的问题

  1. #define定义的宏函数和常量无法被调试
  2. 代码可读性差,可维护性差,并且容易误用
  3. #define定义的宏函数没有类型的检查

在C++中,为了避免上述问题,经常使用constenum来表示常量,而使用内联函数代替#define定义的宏函数

所谓内联函数,即当函数代码量较小时,在汇编代码中直接将函数代码替换掉原来的call+函数名指令,减少函数栈帧开辟时的开销,从而实现直接执行函数,但是缺点也就比较明显,如果代码量太大,将会导致替换后的函数指令很多,为此C++中的内联函数到底是真正的函数还是类似于C语言的宏函数取决于函数代码规模的大小,如果函数代码量大,那么尽管定义为内联函数,还是会被编译器认作普通函数

在C++中,使用inline关键字修饰定义的函数,语法如下

inline + 普通函数定义

代码实例

//C语言中#define定义的ADD宏函数
#define ADD(x, y) ((x) + (y))//C++中内联函数
inline int add(int a, int b)
{return a + b;
}

📌

不建议将内联函数的声明和定义分开写,二者分离会导致链接错误。因为inline会展开函数,导致函数失去本身的地址,声明的函数就无法被找到

//函数声明
inline int add(int a, int b);//函数定义
int add(int a, int b)
{return a + b;
}
//编译报错为链接错误

内联函数的特点

inline是一种以存储空间(不是内存空间)换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大(因为函数展开之后汇编代码量增多),优势:少了调用开销,提高程序运行效率

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/750924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring MVC文件上传配置

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 文件上传 Spring MVC文件上传基于Servlet 3.0实现&#xff1b;示例代码如下&#xff1a; Overrideprotected void customizeRegistration(ServletRegistration.Dynamic reg…

Guitar Pro 8.1功能介绍及如何安装安装破解教程

音乐创作是许多音乐人的核心工作&#xff0c;而吉他作为其中最为常用的乐器之一&#xff0c;其创作和演奏的重要性也不言而喻。在创作过程中&#xff0c;如何更好地记录和编辑音乐成为了许多音乐人所面临的挑战。而Guitar Pro 8.1则是一款专业的吉他音乐编辑软件&#xff0c;它…

T1.数据库MySQL

二.SQL分类 2.1 DDL 2.1.1数据库操作 1). 查询所有数据库 show databases ; 2). 查询当前数据库 select database(); 3)创建数据库 create database [if not exists] 数据库名 [default charset 字符集] [collate 排序规则] ; 4&#xff09;删除数据库 drop database …

【机器学习系列】M3DM工业缺陷检测部署与训练

一.基础资料 1.Git 地址 地址 2.issues issues 3.参考 参考 csdn 二.服务器信息 1.GPU 服务器 GPU 服务器自带 CUDA 安装(前提是需要勾选上)CUDA 需要选择大于 11.3 的版本登录服务器后会自动安装 GPU 驱动 2.CUDA 安装 GPU 服务器自带 CUDA CUDA 版本查看 3.登录信…

欢迎来到实力至上教室-名言(解释来自文心一言)-04

人在这世上是无法独自生存的。因为学校和社会都是由众多人所组成。——绫小路清隆 首先&#xff0c;从生物学的角度看&#xff0c;人类作为社会性动物&#xff0c;天生就具有与他人互动和合作的本能。无论是在原始社会还是现代文明中&#xff0c;人类都需要通过集体合作来确保生…

小红书图片怎么提取?小红书图片提取原图方法!

说到小红书&#xff0c;不少女性群体都知道这个&#xff0c;他的价值很高而且变现对于大多数做自媒体的小伙伴来说&#xff0c;也是不错的选择&#xff01; 小红书对于普通大众还是互联网创作者来说&#xff0c;都太实用了&#xff0c;唯一的缺点可能就是当我们需要存储他的图…

2.VDMA视频流显示通路搭建

1.简介 本节主要讲解如何基于ZYNQ7020搭建一个视频流接收以及显示的数据通路。为后续的算法图像验证提供基础。 2.项目框架 整个项目简略框架如图&#xff0c;img_gen负责产生图像像素点&#xff0c;给到video in to AXI_Stream模块后转化为AXI_Stream数据流给到VDMA&#xff…

STM32---SG90舵机控制(HAL库,含源码)

写在前面&#xff1a;在嵌入式的项目中&#xff0c;舵机是一个十分常见的元器件模块&#xff0c;其主要的功能是实现机械转动&#xff0c;实质上舵机是一个伺服的驱动器&#xff0c;适用于那些需要角度不断变化并可以保持的控制系统。例如在机器人的电控制器系统中&#xff0c;…

深入解析 Kafka生产者:关键特性与最佳实践

引言 Apache Kafka作为一个高度可扩展且具有高效性的消息中间件&#xff0c;已经成为现代大数据生态系统中的核心组件之一。在本文中&#xff0c;我们将专注于Kafka中的一个重要角色——生产者&#xff08;Producer&#xff09;&#xff0c;探讨其核心功能、工作原理及其关键配…

用户数据的FLASH存储与应用(FPGA架构)

该系列为神经网络硬件加速器应用中涉及的模块接口部分&#xff0c;随手记录&#xff0c;以免时间久了遗忘。 一 背景 我们知道&#xff0c;在FPGA做神经网络应用加速时&#xff0c;涉及到权重参数的存储和加载。通常在推理过程中&#xff0c;会将权重参数存储在外部DDR或片上S…

c++简单实现avl树

文章目录 AVL树节点类节点类的构造函数 AVLinsert()插入RotateL(左单旋)RotateR(右单旋)RotateLR(右双旋)RotateRL(左双旋) Find(查找)IsBalance(检查是否是avl树) AVL树 AVL树:又名高度平衡树&#xff0c;在二叉搜索树的基础上加上了一个条件&#xff0c;条件是左右子树高度差…

vulhub中GitLab 远程命令执行漏洞复现(CVE-2021-22205)

GitLab是一款Ruby开发的Git项目管理平台。在11.9以后的GitLab中&#xff0c;因为使用了图片处理工具ExifTool而受到漏洞CVE-2021-22204的影响&#xff0c;攻击者可以通过一个未授权的接口上传一张恶意构造的图片&#xff0c;进而在GitLab服务器上执行任意命令。 环境启动后&am…

[C++ 从入门到精通] 20.对象移动、移动构造函数、移动赋值运算符

📢博客主页:https://loewen.blog.csdn.net📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢本文由 丶布布原创,首发于 CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览: 一. 对象移动的概念二. 移动构造函数和移动赋值…

FFmpeg查看所有支持的编码/解码器/封装/解封装/媒体格式/滤镜

查看所有支持的编码器与解码器 ffmpeg -codecs 只查看所有编码器: ffmpeg -encoders 只查看所有解码器: ffmpeg -decoders 只查看H264编码器: ffmpeg -h encoderh264 只查看H264解码器: ffmpeg -h decoderh264 查看所有支持的封装: ffmpeg -muxers 查看所有支持的解封装…

【开源鸿蒙】为QEMU RISC-V虚拟平台构建OpenHarmony轻量系统

文章目录 一、背景介绍二、准备OpenHarmony源代码三、准备hb命令3.1 安装hb命令3.2 检查hb命令 四、编译RISC-V架构的OpenHarmony轻量系统4.1 设置hb构建目标4.2 启动hb构建过程 五、问题解决5.1 hb set 报错问题解决 六、参考链接 开源鸿蒙坚果派&#xff0c;学习鸿蒙一起来&a…

【每日算法】常见AIGC模型; 刷题:力扣单调栈

上期文章 【每日算法】理论&#xff1a;生成模型基础&#xff1b; 刷题&#xff1a;力扣单调栈 文章目录 上期文章一、上期问题二、理论问题1、stable diffusion模型的网络架构2、T5的网络架构&#xff08;Text-To-Text Transfer Transformer模型&#xff09;3、SDXL模型4、DA…

Git全套教程一套精通git.跟学黑马笔记

Git全套教程一套精通git.跟学黑马笔记 文章目录 Git全套教程一套精通git.跟学黑马笔记1.版本管理工具概念2. 版本管理工具介绍2.1版本管理发展简史(维基百科)2.1.1 SVN(SubVersion)2.1.2 Git 3. Git 发展简史4. Git 的安装4.1 git 的下载4.2 安装4.3 基本配置4.4 为常用指令配置…

【jeecgboot】微服务实战LISM

目录 一、服务解决方案-Spring Cloud Alibaba1.1选用原因&#xff08;基于Spring Cloud Alibaba的试用场景&#xff09;1.2 核心组件使用前期规划 部署 nacos部署 mino使用JavaFreemarker模板引擎&#xff0c;根据XML模板文件生成Word文档使用JavaFlowable 工作流引擎前端 -vue…

SpringBoot中的HttpServletRequest

1.HttpServletRequest javax.servlet.http.HttpServletRequest是SUN制定的Servlet规范&#xff0c;是一个接口&#xff0c;表示请求&#xff0c; 其父接口是 javax.servlet.ServletRequest。“ HTTP 请求协议”的完整内容都被封装到 request对象中。 2.HttpServletRequest的生…

【C++中日期类的实现】

一路&#xff0c;一路&#xff0c;一路从泥泞到风景............................................................................................... 目录 前言 一、【什么是日期类】 二、【代码实现】 1.【Date.h】部分&#xff1a; 2.【Date.cpp】部分&#xff1a;…