C++之从C过渡(上)
C++之从C过渡
前言
暂时告别C语言,我们走进C++。对于有C语言基础,初学C++的我们来说,在正式学习C++的主体内容之前,我们需要先有一个过渡,本文中会总结过渡需要了解的零散知识,主要是语法。
正文
C++的第一个程序
C++兼容C语⾔绝⼤多数的语法,所以C语⾔实现的helloworld依旧可以运⾏,C++中需要把定义⽂件 代码后缀改为.cpp,vs编译器看到是.cpp就会调⽤C++编译器编译,linux下要⽤g++编译,不再是gcc。
// test.cpp
#include<stdio.h>int main()
{printf("hello world\n");return 0;
}
然而C++有⼀套⾃⼰的输⼊输出,严格说C++版本的helloworld应该是这样写的。
// test.cpp
// 这⾥的std cout等看不懂,下面会依次讲解
#include<iostream>
using namespace std;
int main()
{cout << "hello world\n" << endl;return 0;
}
命名空间
这个东西的出现是为了解决C语言中的一些问题。比如:
这是一段C语言代码,问题出在我们包含的stdlib.h这个头文件,我们知道头文件在预处理阶段会展开,也就是会将头文件拷贝过来,而在stdlib.h里有rand函数的定义,所以就与我们定义的变量命名冲突了。
也有可能是我们在与其他人协作时,代码合并后出现了很多冲突。可以说冲突就是C语言的一大问题。
所以我们在C++中有命名空间。
namespace的定义
- 定义命名空间,需要使⽤到namespace关键字,后面跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
- namespace本质是定义出⼀个域,这个域跟全局域各自独立,不同的域可以定义同名变量,所以下面的rand不在冲突了。
- C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/ 类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。
#include<stdio.h>
#include<stdlib.h>//域
namespace oct
{//命名空间中可以定义变量、函数和类型int rand = 10;
}//注意这里是没有分号的int main()
{//编译报错:重定义printf("%d\n", rand);//此时rand已经被封起来了,这里的rand访问的是函数rand//这里如果真的想打印rand,改为%p更好return 0;
}
可以看出上面namespace定义中所说的,这个域跟全局域各自独立。
就近原则
int a = 0;
int main()
{int a = 1;printf("%d\n", a);return 0;
}
在这段代码中,全局和局部都有个a,那么我们打印时访问的是哪个a呢?答案是局部的,这是由于就近原则:先在局部找再去全局找。
那如果我们现在就想要访问全局的这个a,该怎么办呢?
这时候我们就需要用到**“域作用限定符”**,也就是两个冒号。
冒号左边不给东西,就默认去全局域查找了。
那现在我们想要访问namespace里的变量,怎么做呢?
在域作用限定符左侧给上命名空间的名字,也就是告诉编译器直接去这个命名空间中查找。
- 查找不是运行时而是编译时,原则上C/C++编译的时候,用一个函数或者变量都得找到它的声明或者定义。
- 关于生命周期,namespace不影响生命周期,namespace中定义的变量也是全局变量。只不过是访问时只有指定才能找到的全局变量。
- 我们不能在局部定义域(在main里面写namespace)。
在命名空间中定义函数和结构
namespace oct
{//命名空间中可以定义变量、函数和类型int rand = 10;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}
注意,在命名空间中定义结构,我们要访问时的使用方式是这样的:
struct oct::Node p1;
namespace的定义
namespace的前三条定义我们就看完了,现在再看三个定义:
- namespace只能定义在全局,当然他还可以嵌套定义。
- 项⽬⼯程中多⽂件中定义的同名namespace会认为是⼀个namespace,不会冲突。
- C++标准库都放在⼀个叫std(standard)的命名空间中。
命名空间的嵌套定义
在一个公司中我们可能有多个项目组,不同组用不同的命名空间,就不会冲突了。但是对于在同一个项目组的不同人来说,各自在各自的电脑上写,然后要合代码,比如用git提交代码,合起来可能就冲突了。也就是说在一个命名空间内部的冲突。
namespace oct
{namespace october{int rand = 1;int Add(int left, int right){return left + right;}}namespace octopus{int rand = 2;int Add(int left, int right){return (left + right)*10;}}
}
当然还可以再往下嵌套。
那么嵌套的命名空间里的成员如何访问?
多文件同名namespace不会冲突
同一个命名空间我们可以在同一个文件中定义多份,也可以在多个文件中定义多份。
比如我们现在有栈、队列、链表的文件,将它们都封装在namespace oct中,逻辑上会将它们合并,而不是冲突。否则我们一个文件一个命名空间,得定义很多的命名空间,显然不合适。
比如我们现在在全局定义一个静态的栈,再在命名空间定义动态的栈,在使用时我们就可以通过域的隔离分别使用,不会冲突。
C++标准库都放在⼀个叫std(standard)的命名空间中
标准库也怕和别人冲突。
C++标准库也有很多个各自的文件,都用namespace std合并封起来。
命名空间的使用
命名空间的使用有三种方式。
编译查找⼀个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以下面程序会编译报错。所以我们要使⽤命名空间中定义的变量/函数,有三种⽅式:
- 指定命名空间访问,项⽬中推荐这种⽅式。
- using将命名空间中某个成员展开,项⽬中经常访问的不存在冲突的成员推荐这种⽅式。
- 展开命名空间中全部成员,项⽬不推荐,冲突⻛险很⼤,⽇常⼩练习程序为了⽅便推荐使⽤。
上面我们使用的方式是指定命名空间访问。
而每次都指定命名空间还是挺麻烦的。
全展开
现在可以看到,我们就可以不用指定,直接使用命名空间里的a和b了。而这种写法是命名空间全展开。
但是展开整个命名空间的风险是很大的。只适合我们平时写日常小练习程序。
某个成员展开
所以我们还有一种折中的方式:把命名空间中的某个成员展开。
假如我们要频繁使用a,且a不存在冲突风险:
所以一般在项目中我们选择将前两种方法结合使用。
- 注意,在展开头文件和展开命名空间中都提到“展开”,但二者并非同一个意思。展开头文件指的是将这个头文件内容拷贝过来。而展开命名空间相当于我们将用于隔离的墙拆除了。
C++输⼊&输出
- 是Input Output Stream的缩写,是标准的输⼊、输出流库,定义了标准的输⼊、输出对象。
- std::cin是istream类的对象,它主要面向窄字符(narrow characters(of type char))的标准输⼊流。
- std::cout是ostream类的对象,它主要面向窄字符的标准输出流。
- std::endl是⼀个函数,流插⼊输出时,相当于插⼊⼀个换⾏字符加刷新缓冲区。
只有内存里才有整型、浮点型这样的概念,在其他的地方比如文件、网络都是字符流的概念。
整型有原码、反码、补码,浮点数也有自己的存储规则,这都是内存里的存储。内存中有这样的概念是为了方便运算。
不管我们用cout还是printf,整型其实都是转换成字符。比如1234被转换为4个字符然后再输出。-1234被转换成5个字符再输出。任何类型都要转换为字符再输出到控制台。
- <<是流插⼊运算符,>>是流提取运算符。(C语⾔还⽤这两个运算符做位运算左移/右移)
#include<iostream>
using namespace std;//一般选择展开,更方便int main()
{int i = 1234;int j = -1234;cout << i << endl;}
- 使⽤C++输⼊输出更⽅便,不需要像printf/scanf输⼊输出时那样,需要⼿动指定格式,C++的输⼊ 输出可以自动识别变量类型(本质是通过函数重载实现的,这个以后会讲到),其实最重要的是 C++的流能更好的⽀持⾃定义类型对象的输⼊输出。
我们的插入可以一次写很多个连一起。
#include<iostream>
using namespace std;int main()
{int a = 0;double b = 0.1;char c = 'x';cout << a << " " << b << " " << c << endl;return 0;
}
还可以这样写:
cout << a << " " << b << " " << c << "\n";
在C++中用"\n"也可以换行。
而这样写就不行:
cout << a " " ;
cout也就是流插入其实是函数调用,只能有一个参数。<<是二元操作符,只能有两个操作数。
可以看到,C语言需要指定类型,比较麻烦,而C++却可以自动识别。
我们再来试试输入(流提取)。
从控制台中提取然后转化成对应的类型。
可以看到可以一次输入多个。
endl比较复杂,是一个函数。它的底层不是一个换行符。其实cout和cin也很复杂。这些都需要日后学得更深入再具体了解。
-
IO流涉及类和对象,运算符重载、继承等很多面向对象的知识,这些知识我们日后讲解。
-
cout/cin/endl等都属于C++标准库,C++标准库都放在⼀个叫std(standard)的命名空间中,所以要通过命名空间的使⽤⽅式去⽤他们。
-
这⾥我们没有包含<stdio.h>,也可以使⽤printf和scanf,在包含间接包含了。vs系列编译器是这样的,其他编译器可能会报错。
小细节:
关于C语言中的控制精度:
可以看到我们的C++是默认保留小数点后5位。也可以人为控制,但是不建议了解。在我们想要控制时,可以用回printf。
在用scanf时我们需要取地址,因为scanf是个函数,[形参的改变不会影响实参,所以我们要取地址。]而在C++中我们就无需取地址。
再次总结,io流函数的定义在iostream头文件里的std命名空间里,可以自动识别类型,可以一行多个输入输出。
补充:
#include<iostream>using namespace std;int main()
{// 在io需求⽐较⾼的地⽅,如部分⼤量输⼊的竞赛题中,加上以下3⾏代码 // 可以提⾼C++IO效率 ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);return 0;
}
C++的IO流由于各种各样的原因比如要兼容C语言,而这种兼容会付出一些代价。IO输入输出是带缓冲区的,各自有各自的缓冲区,要兼容就得去关注对应的缓冲区。为了提高性能,除了换用printf、scanf,还可以选择把这三句代码加上。
缺省参数
• 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调用该函数时,如果没有指定实参则采⽤该形参的缺省值,否则使用指定的实参,缺省参数分为全****缺省和半****缺省参数。(有些地方把缺省参数也叫默认参数)
• 全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。
• 带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。
• 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。
#include <iostream>using namespace std;void Func(int a = 0)//缺省参数
{cout << a << endl;
}int main()
{Func(); // 没有传参时,使⽤参数的默认值 Func(10); // 传参时,使⽤指定的实参 return 0;
}
其实就是如果有传就用传的,没有就用默认的值(缺省值)。
#include <iostream>
using namespace std;// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}// 半缺省
void Func2(int a, int b = 10, int c = 20)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}int main()
{Func1();//一个都不传Func1(1);//传一个Func1(1,2)//传两个Func1(1,2,3);//全传Fun1(,2,);//这样传不可以Func2();//不能一个都不传Func2(100);//传一个Func2(100, 200);//传两个Func2(100, 200, 300);//全传return 0;
}
注意半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。
缺省参数在实践中的意义
之前我们在写栈的插入数据时,如果后续要插入很多数据我们就要多次扩容,效率低下,而如果初始化时一把开好,就可以避免扩容。我们可以使用缺省参数:
(test.cpp中)
#include<iostream>
using namespace std;#include"Stack.h"int main()
{// 确定知道要插入1000个数据,初始化时一把开好,避免扩容moon::ST s2;moon::STInit(&s2, 1000);for (size_t i = 0; i < 1000; i++){moon::STPush(&s2, i);}return 0;
}
(stack.h中)
void STInit(ST* ps, int n = 4);
(stack.cpp中)
这样我们就一把开好,不需要扩容,效率就得到了提高。在我们不知道多大时,不传参数,默认就为缺省参数。
缺省参数是很好用的,日后就知道了。
函数重载
C++⽀持在同⼀作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。这样C++函数调用就表现出了多态行为,使用更灵活。C语言是不⽀持同⼀作⽤域中出现同名函数的。
这个东西非常有用。可以说是C语言的一大缺陷。
#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{cout << "int Add(int left, int right)" << endl;return left + right;
}double Add(double left, double right)
{cout << "double Add(double left, double right)" << endl;return left + right;
}int main()
{Add(1,2);Add(1.1,2.2);return 0;
}
以上代码,C语言是无法做到的。这种情况能同名显然是更好的。
再如
void Swap(int* px,int* py)
{}void Swap(double* px, double* py)
{}
交换函数,如果能够同名,显然是非常好。
// 2、参数个数不同
void f()
{cout << "f()" << endl;
}void f(int a)
{cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同(本质也是类型不同)
void f(int a, char b)
{cout << "f(int a,char b)" << endl;
}void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}
坑:
// 下⾯两个函数构成重载,因为参数个数不同
// f()但是调用时,会报错,存在歧义,编译器不知道调⽤谁 void f1()
{cout << "f()" << endl;
}void f1(int a = 10)
{cout << "f(int a)" << endl;
}
//返回值不同不能作为重载条件,因为调⽤时也⽆法区分
void fxx()
{}int fxx()
{return 0;
}
引用
这也是C++中非常好用的一个东西。
引用的概念和定义
引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间, 它和它引⽤的变量共⽤同⼀块内存空间。⽐如:⽔壶传中李逵,宋江叫"铁⽜",江湖上⼈称"黑旋风";林冲,外号豹⼦头;
类型&引用别名=引用对象;
C++中为了避免引⼊太多的运算符,会复⽤C语⾔的⼀些符号,⽐如前面的<<和>>,这⾥引⽤也和取地址使⽤了同⼀个符号&,从使⽤⽅法⻆度区分就可以。
#include<iostream>
using namespace std;int main()
{int a = 0;// 引⽤:b和c是a的别名 int& b = a;int& c = a;// 也可以给别名b取别名,d相当于还是a的别名 int& d = b;++d;// 这⾥取地址我们看到是⼀样的 cout << &a << endl;cout << &b << endl;cout << &c << endl;cout << &d << endl;return 0;
}
无论叫a b c还是d,都是同一块空间的名字。给其中一个名字加1,其他的名字的值也都加1。
引用的实践
以前我们要交换两个变量的值,得使用传地址的方式。
我们现在使用引用,就无需传地址也能交换两个变量的值。
理解这个我们不要去想底层(底层也是指针),在语法层面就是取别名。
也就是rx是x的别名,ry是y的别名。改变别名就能改变本身。这样并没有为形参开辟新的空间。
我们可能会见到以下的代码:
void STInit(ST& rs, int n = 4)
{rs.a = (STDataType*)malloc(n * sizeof(STDataType));rs.top = 0;rs.capacity = n;
}
这里就用别名来替换了指针。
再或者这样:
// 栈顶
void STPush(ST& rs, STDataType x)
{//assert(ps);// 满了, 扩容if (rs.top == rs.capacity){printf("扩容\n");int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;STDataType* tmp = (STDataType*)realloc(rs.a, newcapacity *sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}rs.a = tmp;rs.capacity = newcapacity;}rs.a[rs.top] = x;rs.top++;
}
有了引用之后进入函数我们就不需要断言了。
还有原本下面的这个函数,我们是要用二级指针作为参数的,因为可能链表为空,push的这个就要成为头结点,那么plist就会改变,而如果参数为一级指针,phead改变无法改变plist,于是我们用二级指针。
void ListPushBack(LTNode*& phead, int x)
{PNode newnode = (PNode)malloc(sizeof(LTNode));newnode->val = x;newnode->next = NULL;if (phead == NULL){phead = newnode;}else{//...}
}int main()
{LTNode* plist = NULL;ListPushBack(plist,1);return 0;
}
而现在我们可以给指针取别名,就不用二级指针。所以我们现在改变指针phead,就是改变main中的指针plist。
typedef struct ListNode
{int val;struct ListNode* next;
}LTNode, *PNode;//等价于
typedef struct ListNode* PNode;
PNode是指向LTNode类型的指针(结构体指针)。
所以上面函数也可以写成
void ListPushBack(PNode& phead, int x)
本文到此结束,但过渡内容没有结束,敬请期待下文=_=
相关文章:

C++之从C过渡(上)
C之从C过渡 前言 暂时告别C语言,我们走进C。对于有C语言基础,初学C的我们来说,在正式学习C的主体内容之前,我们需要先有一个过渡,本文中会总结过渡需要了解的零散知识,主要是语法。 正文 C的第一个程序 …...
MongoDB 100问
基础问题 1. 什么是MongoDB? MongoDB是一种面向文档的NoSQL数据库,使用BSON(二进制JSON)格式存储数据。它支持动态模式设计,具有高性能、高可用性和易扩展性。 2. MongoDB和传统关系型数据库的区别是什么?…...
Arduino ESP32使用 HardwareSerial创建一个任意串口
文章目录 前言使用 `HardwareSerial` 创建任意串口创建 `HardwareSerial` 对象示例代码`begin` 函数总结前言 在 Arduino 项目中,串口通信是一种常见且重要的通信方式。ESP32 作为一款功能强大的微控制器,提供了多个 UART(通用异步收发传输器)接口,允许用户灵活地进行串口…...

数据中台建设之数据存储
目录 一、技术选型需要明确的问题 二、技术选型需要考虑的几个方面 2.1 数据规模 2.2 数据生产方式 2.3 数据应用方式 三、技术选型的场景分析 3.1 概述 3.2 在线与离线 3.2.1 在线存储 3.2.2 离线存储 3.3 OLTP与OLAP 3.3.1 OLTP 3.3.2 OLAP 3.3.3 OLTP与OLAP的关…...

最常见的AI大模型总结
前言:大模型可以根据其主要的应领域和功能,可以分类为“文生文”(Text-to-Text)、“文生图”(Text-to-Image)和“文生视频”(Text-to-Video),都是基于自然语言处理&#…...
源码安装docker和docker-compose
前言 前提条件:内核要求 目前,CentOS 仅发行版本中的内核支持 Docker。 Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为3.10 以上。 Docker 运行在 CentOS-6.5 或更高的版本的 CentOS 上,要求系统为64位、系统内核版…...

Java、PHP、Node 操作 MySQL 数据库常用方法
一、Java 操作 MySQL 数据库 1、Java 连接 MySQL 数据库 1. 使用 JDBC 驱动程序连接 使用这种方式,首先需要导入 MySQL 的 JDBC 驱动程序依赖,然后通过 Class.forName() 方法加载驱动程序类。其创建连接的过程相对直接,只需提供准确的数据库…...

nVisual分享社区正式上线啦!
nVisual分享社区正式上线啦! 访问地址:分享社区 nVisual是耐威迪基于数字孪生技术物联网技术开发的一款基础设施数字孪生软件工具,主要实现OSP室外与ISP室内基础设施的规划、记录、分析的可视化管理。 规划:nVisual可视化、智能化…...

4.5.门控循环单元GRU
门控循环单元GRU 对于一个序列,不是每个观察值都是同等重要的,可能会遇到一下几种情况: 早期观测值对预测所有未来观测值都具有非常重要的意义。 考虑极端情况,第一个观测值包含一个校验和,目的是在序列的末尾辨别…...
10种 Python数据结构,从入门到精通
今天我们将深入探讨 Python 中常用的数据结构,帮助你从基础到精通。每种数据结构都有其独特的特点和适用场景,通过实际代码示例和生活中的比喻,让你更容易理解这些概念。 学习数据结构的三个阶段 1、掌握基本用法:使用这些数据结…...

【AI】人工智能时代,程序员如何保持核心竞争力?
目录 程序员在AI时代的应对策略1. 引言2. AI在编程领域的影响2.1 AI辅助编程工具的现状2.2 AI对编程工作的影响2.3 程序员的机遇与挑战 3. 深耕细作:专注领域的深度学习3.1 专注领域的重要性3.2 深度学习的策略3.2.1 选择合适的领域3.2.2 持续学习和研究3.2.3 实践与…...

WPF学习(3)- WrapPanel控件(瀑布流布局)+DockPanel控件(停靠布局)
WrapPanel控件(瀑布流布局) WrapPanel控件表示将其子控件从左到右的顺序排列,如果第一行显示不了,则自动换至第二行,继续显示剩余的子控件。我们来看看它的结构定义: public class WrapPanel : Panel {pub…...

【python】Python中实现定时任务常见的几种方式原理分析与应用实战
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

老公请喝茶,2024年老婆必送老公的养生茶,暖暖的很贴心
在这个快节奏的时代,每个人都在为生活奔波,而家的温馨与关怀,成了我们最坚实的后盾。随着2024年的已经过半,作为妻子,你是否也在寻找一份特别的礼物,来表达对老公深深的爱意与关怀?在这个充满爱…...
3d打印相关资料
模型库 拓竹makerworld爱给...

MySQL1 DDL语言
安装与配置 官网: MySQL :: Download MySQL Installer 阿里云: MySQL8 https://www.alipan.com/s/auhN4pTqpRp 点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速…...

el-tree懒加载状态下实现搜索筛选(纯前端)
1.效果图 (1)初始状态 (2)筛选后 2.代码 <template><div><el-inputplaceholder"输入关键字进行过滤"v-model"filterText"input"searchValue"></el-input><el-tree…...

NLP——Transfromer 架构详解
Transformer总体架构图 输入部分:源文本嵌入层及其位置编码器、目标文本嵌入层及其位置编码器 编码器部分 由N个编码器层堆叠而成 每个编码器层由两个子层连接结构组成 第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接 第二个子层连接结构包…...

大模型算法面试题(二十)
本系列收纳各种大模型面试题及答案。 1、描述Encoder和Decoder中Attention机制的不同之处 Encoder和Decoder中的Attention机制在自然语言处理(NLP)和序列到序列(Seq2Seq)模型中扮演着重要角色,它们虽然都利用了Attent…...

2024最新最全面的Selenium 3.0 + Python自动化测试框架
文档说明 Selenium是一个用于Web应用程序自动化测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。 Selenium测试的主要功能包括: 测试与浏览器的兼容性:测试应用程序是否能很好的工作在不同的浏览器和操作系统之上。…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...