C++基础讲解
C++基础讲解
- 序言
- 1 命名空间
- 1.1 命名空间的作用
- 1.2,命名空间的定义
- 1.3 命名空间的使用
- 2 C++输入与输出
- 3 缺省参数
- 4 函数重载
- 5 引用
- 5.1 引用的概念与特性
- 5.2 引用的使用
- 5.2.1 引用传参
- 5.2.2 引用做返回值
- 5.2.2.1采用引用返回:
- 5.2.2.2采用值返回的情形:
- 5.2.2.3 函数返回值与左值右值的关联
- 5.3 const引用
- 5.4 指针和引用关系
- 6 inline修饰的内联函数
- 7 空指针nullptr
序言
由于C语言在语言表达、可维护性、和可扩展性等方面缺陷突出,所以在1983年本贾尼博士在C语言的基础上添加了面向对象编程的的特性,设计出了C++语言。由于C++是对C语言的发展和继承,所以C++中兼容C语言的绝大多数语法。但定义文件代码后缀需要改为 .cpp,Linux系统下不再用gcc编译,而是g++;vs编译器下会直接调用C++编译器。
1 命名空间
1.1 命名空间的作用
在C语言中,我们有时会发现,我们在新包含一个头文件后竟然出现了报错。比如我们自定义了一个rand
变量,当我们包含了<stdlib>
这个头文件后,出现了编译报错:C2365 “rand”: 重定义;以前的定义是函数。这是因为rand以前的定义是stdlib这个库中的函数,出现了命名冲突。所以针对这一问题C++中做了命名空间这一关键字。
#include<stdio.h>
#include<stdlib.h>int rand = 3;
int main()
{printf("%d\n", rand);return 0;
}
1.2,命名空间的定义
命名空间从本质上来讲是定义出了一个域,C++中有函数局部域、全局域、命名空间域和类域。命名空间域的定义需要用到关键字namespace
,其定义语法为namespace _name{ }
,{}中的即为命名空间的成员。命名空间中可以定义变量、函数、类型等。namespace
只能定义在全局,但它可以实现嵌套定义。命名空间域与全局域各自独立,不同的域中可以定义同名变量。且项目工程中多文件中定义的同名namespace
会认为是一个namespace
,它们会默认自动合并为一个命名空间域,不会冲突。
在这里要着重强调一下,C++的标准库都被封装在叫std
(standard)的命名空间中。
代码演示:
1、定义一个命名空间:
//命名空间最后不要加;
namespace ZSY
{
//把自定义rand放到命名空间里就不会出现上面的命名冲突int rand = 8;struct List{struct List* next;int data;};int mod(int num1, int num2){return num1 % num2;}
}int main()
{int mod = 5;//打印的是局部变量mod的值printf("%d\n", mod);//打印的是命名空间中mod函数的指针printf("%p\n", ZSY::mod);return 0;
}
2、命名空间的嵌套定义:
namespace classmates
{namespace YHQ{int age = 88;}namespace WSB{int age = 89;}
}int main()
{//打印classmates下YHQ下的age变量printf("YHQ_age == %d\n", classmates::YHQ::age);//打印classmates下WSB下的age变量printf("WSB_age == %d\n", classmates::WSB::age);return 0;
}
1.3 命名空间的使用
程序在编译阶段去查找一个变量的声明和定义时,默认只会在局部和全局查找且符合就近原则,不会到命名空间里去查找。所以当我们要使用命名空间里定义的变量、函数时,有三种方式:
1、指定命名空间访问(最推荐)
2、using
将命名空间中某个成员展开(当经常访问不存在冲突的成员时最推荐)
3、展开命名空间中的全部成员(做项目时极不推荐,造成成员冲突的风险很大,但可以直接展开C++的std
域,此外在日常练习时无关紧要)
代码演示:
演示前先介绍一种操作符:作用域解析运算符"::
"
1、指定命名空间访问:
namespace Bye
{int b = 10;
}int main()
{printf("b == %d\n", Bye::b);return 0;
}
2、using
将命名空间中某个成员展开:
namespace data
{int a = 1;int b = 2;
}
//只展开命名空间里的 b
using data::b;
int main()
{printf("a == %d", data::a);printf("b == %d", b);
}
3、展开命名空间中的全部成员:
namespace data
{int a = 1;int b = 2;
}
//展开命名空间里的全部成员
using namespace data;
int main()
{printf("a == %d", a);printf("b == %d", b);return 0;
}
注:此处我们所提的展开命名空间的 “ 展开 ” 与展开头文件里的 “ 展开 ” 不是同一个意思。展开命名空间的展开好比打破了限制访问命名空间里成员的一堵墙;展开头文件则是对头文件内容的实行拷贝。
2 C++输入与输出
<iostream
>是C++标准的输入输出流库,其中定义了标准的输入与输出对象。<iostream>
都被封装在命名空间std
之中,在导入标准输入输出库后还应对std进行全展开或者对需要使用的部分进行展开。std::cin
是istream
类的对象,它主要面向窄字符的标准输入流。std::cout
是ostream
类的对象,它主要面向窄字符的标准输出流。std::endl
是一个函数,流插入输出时,等同于插入了一个换行字符同时刷新缓冲区。注意std::endl
不可以完全等同于C语言当中的\n
,\n
虽然也能起到换行的作用,但是只有在部分条件下才能立即刷新缓冲区,与std::endl
仍然存在差异。<<
是流插入运算符(C语言中位运算的左移),>>
是流提取运算符(C语言中位运算的右移)。- C++中的输入输出与C语言相较更加简便,C++的输入输出可以自动识别变量类型,不需要像C语言的
scanf/printf
手动设置变量类型。更重要的是C++的流能更好的支持自定义类型对象的输入输出。(主要归功于运算符重载和面向对象编程) - 在VS系列编译器中,包含
<iostream>
会间接包含<stdio.h>
,但在其他编译器中不一定包含(如Linux下的g++)。
using namespace std;int main()
{int ab = 10;double bc = 12.1;char cd = 'v';//流输出cout << ab << " " << bc << " " << cd << endl;std::cout << ab << " " << bc << " " << cd << std::endl;//手动设置输出格式printf("%d %f %c\n", ab , bc , cd);//流输入cin >> ab >> bc;//手动设置输入格式scanf_s(" %c", &cd);cout << ab << " " << bc << " " << cd << endl;return 0;
}
在IO流需求较高处,可以加上以下3行代码,可以提高C++ IO效率。
int main()
{//提高C++ IO效率ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);return 0;
}
3 缺省参数
缺省参数是在声明或定义是给函数的参数设置一个缺省值。在调用该函数时,若没有相应实参传入,就采用该形参的缺省值;反之,则使用指定的实参。缺省参数分为全缺省和半缺省。(缺省参数有时也称为默认参数)
缺省参数设置规则如下:
- 当函数的定义与声明分离时,缺省参数规定必须在函数声明处给缺省值,不能在函数定义与声明中同时出现。
- 全缺省就是全部参数给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左依次缺省,不能间隔给缺省值。
- C++规定带缺省参数的函数调用,必须从左往右依次给实参,不能跳跃给实参。
代码演示:
1、传参与不传参时缺省参数效果:
void Disp1(int a = 5)
{cout << a << endl;
}int main()
{Disp1(); //未传参时,使用参数默认值Disp1(10);//传参时,使用指定的实参return 0;
}
2、全缺省与半缺省:
using namespace std;//全缺省
void Disp1(int a = 10, int b = 20, int c = 30)
{cout << "a == " << a << endl;cout << "b == " << b << endl;cout << "c == " << c << endl;cout << " " << endl;
}//半缺省
void Disp2(int c, int d = 40, int e = 50)//从右往左依次设置缺省值
{cout << "c == " << c << endl;cout << "d == " << d << endl;cout << "e == " << e << endl;cout << " " << endl;
}int main()
{//从左往右依次指定实参Disp1();Disp1(100);Disp1(100, 200);Disp1(100, 200, 300);Disp2(100);Disp2(100, 200);return 0;
}
4 函数重载
C++中支持同一作用域中出现同名函数,但要求这些同名函数的形参不同而不是返回值类型不同,可以是参数个数不同或者参数类型不同。如此C++函数的调用就表现出了多态行为,更为灵活。而C语言是不支持同一作用域中出现同名函数的。
1、形参类型不同:
//参数类型不同
using namespace std;
//参数类型为整型
int Multiplication(int a = 10, int b = 5)
{return a * b;
}
//参数类型为浮点型
float Multiplication(float a = 10.0 , float b = 1.1)
{return a * b;
}int main()
{//调用函数,实现函数重载int x = Multiplication(12,13);float y = Multiplication(11.0f, 12.1f);cout << "int Multiplication(int a = 10, int b = 5)" << endl;cout << x << endl;cout << "float Multiplication(int a = 10, int b = 5)" << endl;cout << y << endl;return 0;
}
2、形参个数不同:
//形参个数不同
using namespace std;
//一个形参
int division(int a)
{return a;
}
//两个形参
double division(double c , double d)
{return c - d;
}int main()
{//调用函数,实现函数重载int x = division(8);double y = division(12.2, 0.2);cout << "int division(int a)" << endl;cout << x << endl;cout << "double division(double c , double d)" << endl;cout << y << endl;return 0;
}
3、参数类型顺序不同:
//参数类型顺序不同
using namespace std;void inf(char* x , int a)
{cout << "姓名:" << x << " " << "年龄:" << a << endl;
}void inf(int a , char* x)
{cout << "体重(kg):" << a << " " << "营养状况:" << x << endl;
}int main()
{char name[5] = "";int age;int weight;char situation[5] = "";cin >> name >> age >> weight >> situation;inf(name, age);inf(weight, situation);return 0;
}
4、避免如下歧义编写:
下面这两个函数构成函数重载,但c1()
在调用时会报错,存在歧义,编译器不知道调用谁。
//避免下面存在歧义的编写
using namespace std;
void c1()
{cout << "hello" << endl;
}
void c1(int a = 10)
{cout << a << endl;
}int main()
{c1();return 0;
}
5 引用
5.1 引用的概念与特性
引用可以理解为给现有的变量取一个别名,而非定义一个新的变量。编译器不会给这个引用变量开辟内存空间,引用变量是和它所引用的对象共用同一块内存空间(注意:这里所说的对象是笼统意义上的对象,包括了类实例化的对象、临时副本和内置类型对应数据。下文若无特殊说明,对象均为此含义)。对于引用的理解,我们可以类比不同人对诸葛亮的称呼,比如诸葛亮本名就是诸葛亮,刘备叫他军师、丞相后者卧龙先生,徐庶叫他孔明,这些别人对他的称呼就等同于我们所提的引用。
引用的语法格式:类型& 引用别名 = 引用对象
。注意,在C++中为了避免引入过多的运算符,复用了一些C语言的运算符,比如前文所提的流插入和流提取运算符(<<和>>
),&
也是一样,在C++中既能表示取地址运算,也可以用于引用。
引用的特性有以下三点:
- 引用在定义时必须初始化
- 一个变量可以有多个引用
- 引用一旦引用了一个实体,再不能引用其他实体。
注意:这只是在C++中引用的特性,在其他语言中会有差异,比如在JAVA中引用可以改变其指向,而在C++中却不行。
using namespace std;int main()
{int x = 10;//初始化引用变量int& y = x;int z = 0;//想改变引用变量y的指向,但是C++中不允许这么操作,所以下面的命令就是赋值命令y = z;//因为y是x的别名,修改了y也等同于修改了x,所以x、y、z都是0cout << x << endl;cout << y << endl;cout << z << endl;//x与y地址相同,二者与z的存储地址不同cout << &x << endl;cout << &y << endl;cout << &z << endl;
}
5.2 引用的使用
- 引用主要用于(1)引用传参和引用做返回值中减少拷贝提升效率 (2)改变引用变量时同时改变被引用的实体。 因为引用传递是直接通过别名访问原始对象,所以无需拷贝,也可直接改变原始对象。
- 引用传参与指针传参功能是类似的,引用传参相对更方便一些。
- 引用和指针在实践中是相辅相成的,二者的功能虽然近似,但是仍有不同,二者间不存在替代关系。
以下代码分别展示引用传参和引用做返回值的情况:
5.2.1 引用传参
void change(int& a, int& b)//x与y传上来后,a与b就是它俩的别名,改变a、b就是改变x、y
{a++;b++;
}int main()
{int x = 10 , y = 20;cout << "初始x的值:" << x << " \n" << "初始y的值:" << y << endl;change(x, y);cout << "改变后x的值:" << x << " \n" << "改变后y的值:" << y << endl;return 0;
}
上面这段代码就是形参处用引用来接受传参,如此一来形参的改变就可以直接影响实参,而不需要使用指针来接受传参,且避免了因传值传参需要拷贝而额外在栈区开辟空间,提升了运行效率。
5.2.2 引用做返回值
5.2.2.1采用引用返回:
int& getnum()
{static int c = 10;return c;
}int main()
{int x = 50;cout << "初始c值:" << getnum() << endl;//此处返回的是c的别名,下面就是把x的值赋值给c的别名getnum() = x;cout << "改变后c值:" << getnum() << endl;return 0;
}
5.2.2.2采用值返回的情形:
int getnum()
{static int c = 10;return c;
}int main()
{int x = 50;cout << "初始c值:" << getnum() << endl;//此处返回的不是引用,而是值。左值是不能被改变的,所以报错getnum() = x;cout << "改变后c值:" << getnum() << endl;return 0;
}
在上面的代码中,函数采用值返回的格式,当函数调用后会为返回的对象创建一个临时对象(临时副本),返回值返回的是这个临时对象而非原始对象,C++规定临时对象具有常性且临时对象和原始对象是各自独立存在的,所以修改临时对象内的内容是不会影响到原始对象的。
此外,函数采用值返回时,函数的返回值是右值,右值通常只能赋值给其他实体而不能被其他实体赋值。所以上面代码中getnum() = x;
的报错表示为左侧函数的返回值应当是可以被修改的左值,即应当返回引用。
特殊说明:
内置类型成员在进行传参,按值返回或类型转换等情况时编译器会把数值直接复制到寄存器或栈,寄存器或栈上的数据就是我们所说的临时副本即笼统意义上的对象。
自定义类型成员在进行传参,按值返回等情况时编译器会创建临时对象(这个对象是类和对象概念中的对象含义),通常创建在栈区,拷贝行为会调用拷贝构造函数(类和对象章节会进行讲解)。
5.2.2.3 函数返回值与左值右值的关联
由上可知,函数采用按值返回时,其返回值是右值;采用按引用返回时,其返回值是左值。从之前链表章节我们可知,函数的返回值是指针时,我们依然可以对这个指针指向的内容进行改变,那么采用指针返回时,返回值是左值吗?
对于这个问题我们要知道当指针作为返回值返回到调用处后,其返回的是一个地址值,这个地址值指向某个内存位置,尽管指针本身在函数返回时是一个右值(因为它是一个临时的、不可修改的地址值),但是这个地址值所指向的内存位置可能是一个可修改的变量(因为这块内存位置可能存储的的具有常性的数据)。
//返回值是指针
int* getnum()
{static int c = 10;return &c;
}int main()
{int x = 50;cout << "初始c值:" << *getnum() << endl;//这里返回的是一个地址值,解引用后其所指向的内存位置是可以修改的* getnum() = x;cout << "改变后c值:" << * getnum() << endl;return 0;
}
5.3 const引用
const
引用既可以引用一个const
对象,也可以引用一个普通对象,因为对象的访问权限在引用的过程中可以缩小,但不能放大。(普通引用来引用const
对象就是权限放大,由可读不可写放大为可读可写,这是不允许的;const
引用来引用普通对象就是权限缩小,由可读可写缩小为可读不可写,这是允许的)- **在C++中若对生成的临时对象进行引用,也需要使用const引用。**在C++中临时对象指的是编译器需要一个空间暂存表达式的求值结果时临时创建的一个未命名的对象,且C++规定这类临时对象具有常性。
常见的生成临时对象的情景有:
1、±等产生的运算结果;2、类型转换;3、传参;4、返回值。
在上图中,左侧是给a+b生成的临时对象定义了一个const引用;右侧看似pa是a的引用,实则pa引用的是隐式类型转换时生成的临时对象,所以a的类型不变仍是double,pa则是将生成的临时对象的值截断为int类型。
5.4 指针和引用关系
C++中指针和引用是相辅相成的,各有特点,相互之间有重叠性但又相互不可替代。
3. 语法概念上引用是一个变量的别名,不开空间。指针是存储一个变量的地址,要开空间。
4. 引用定义时必须初始化,而指针是建议初始化,其在语法上未做要求。
5. 在C++中,引用一旦初始化后就不可改变指向,而指针是可以不断改变指向对象。
6. 引用可以直接访问指向对象,而指针需要解引用才能访问指向对象。
7. 二者在关键字sizeof
中含义不同,引用的结果是其引用类型的大小,但指针的大小始终是地址空间所占的字节个数(x86下是4字节,x64下是8字节)
8. 指针若不及时置空,极易出现空指针或野指针的问题。而引用却很少出现,相对而言使用引用更安全一些。(比如函数采用引用返回,但是返回值却是函数内的局部变量,生命周期结束函数销毁,此时引用就为空)
6 inline修饰的内联函数
inline
修饰的函数称为内联函数,C++编译器编译时会在调用处展开内联函数,这样函数就不需要建立栈帧,可以提效。inline
对于C++编译器来说只是一个建议,有时即使你对函数使用inline
修饰,编译器也可以选择在调用的地方不展开,这取决于编译器的类型与版本,不同编译器针对inline
有不同的结果,因为C++中并未对此作出规定。inline
适用于频繁调用的短小函数,对于递归函数或代码较多的函数,即使加上inline
也会被编译器忽略。- C++中设计
inline
的目的主要是替换C语言中的宏函数。虽然宏函数也会在预处理时展开,但是宏函数实现相对复杂易出错,不便于调试。故使用inline
修饰的内联函数可最大程度规避这些问题。 inline
不建议定义与声明分离到两个文件,分离会导致链接错误。学习完C语言后我们知道,常规函数调用如果函数的声明和定义分离时,函数在完成定义的同时会生成一个外部符号(接口),函数的声明就是告知编译器函数的接口(返回类型、函数名、参数类型),链接时通过该接口找到所调用函数的地址。而定义inline
修饰的内联函数时,编译器不会为其生成外部符号,所以当声明和定义分离到两个文件时,链接器无法找到外部符号从而无法找到要调用函数的地址,导致链接错误。正确的做法应当是将函数的声明和定义放到同一头文件中。- VS编译器的Debug版本下为了方便调试,默认是不展开
inline
的。
//内联函数声明
inline void swap(int* a, int* b);//内联函数定义
void swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}int main()
{int x = 1;int y = 2;swap(&x, &y);cout << x << endl;cout << y << endl;return 0;
}
7 空指针nullptr
在C语言中空指针NULL
是一个宏,其被定义为无类型指针(void*)的常量。但在C++的头文件中,对NULL
的宏定义是这样的:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0 // C++中定义为0(整型)
#else
#define NULL ((void*)0) // C中定义为void*指针
#endif
#endif
所以在C++中,NULL
的定义不会是void*
类型,而是被定义为整型字面量0。这是因为C语言中void*
允许进行隐式指针转换而C++中是不允许的。
由此拓展一下为什么C++中不能将NULL定义为void*
?
原因一:C++的类型安全要求:
C++不允许将void*
隐式转换为其他指针类型(如int*
或char*
)。如果NULL
被定义为void*
,则以下代码会导致编译错误:
int* p = NULL; // 如果NULL是void*,C++需要显式类型转换
因此,C++将NULL
定义为整型0,可以隐式转换为任何指针类型(如int*
或char*
),从而兼容旧代码。
原因二:函数重载的歧义问题:
//函数1
void f1(int a = 10)
{cout << a << endl;
}
//函数2
void f1(char* x)
{cout << x << endl;
}int main()
{f1(NULL);// NULL是0,调用函数1return 0;
}
上面代码中想通过传空指针来调用函数f1(char* )
时,由于空指针NULL
被定义为了0,会调用f(int )
,与程序初衷相悖。
所以为了解决上面的问题,C++11中引入了关键字nullptr
,它是一种特殊类型的字面量(空指针常量),它可以转换成任意其他类型的指针类型。使用nullptr
定义空指针可以避免类型转换的问题,因为nullptr
只能被隐式转换为指针类型,而不能被转换为整型。
int* p = nullptr; // 正确,无需类型转换
func(nullptr); // 明确调用指针版本的函数
全文至此结束!!!
写作不易,不知各位老板能否给个一键三连或是一个免费的赞呢(▽)(▽),这将是对我最大的肯定与支持!!!谢谢!!!(▽)(▽)
相关文章:
C++基础讲解
C基础讲解 序言1 命名空间1.1 命名空间的作用1.2,命名空间的定义1.3 命名空间的使用 2 C输入与输出3 缺省参数4 函数重载5 引用5.1 引用的概念与特性5.2 引用的使用5.2.1 引用传参5.2.2 引用做返回值5.2.2.1采用引用返回:5.2.2.2采用值返回的情形:5.2.2.…...
【代码模板】判断C语言中文件是否存在?错误:‘F_OK’未声明如何处理?(access;#include “unistd.h“)
#include "stdio.h" #include "unistd.h"int main(int argc, char *argv[]) {if (access("./1.cpp", F_OK) -1) {printf("not exist\n");} else {printf("exist\n");} }报错 错误:‘F_OK’未声明 需要包含#inc…...
form实现note笔记本新建保存加密功能
说明: 我希望用form实现笔记本新建保存加密功能 笔记管理应用,具备创建、保存、删除笔记的功能,并且有简单的加密保护。 1.笔记管理:1.1新建笔记:清除标题和内容,取消列表选择。1.2保存笔记:验…...
【算法竞赛】状态压缩型背包问题经典应用(蓝桥杯2019A4分糖果)
在蓝桥杯中遇到的这道题,看上去比较普通,但其实蕴含了很巧妙的“状态压缩 背包”的思想,本文将从零到一,详细解析这个问题。 目录 一、题目 二、思路分析:状态压缩 最小覆盖 1. 本质:最小集合覆盖问题…...
【C++初阶篇】C++中c_str函数的全面解析
C中c_str函数的全面解析 1. c_str()函数的定义与原型2. c_str()函数的返回值特性3 c_str()函数的使用场景3.1 与C标准库函数交互3.2 文件操作3.3 系统调用 4. c_str()函数的注意事项4.1 返回指针的只读性4.2 生命周期问题4.3 空字符串处理4.4 避免直接赋值给char* 5. c_str()函…...
Python 匿名函数(Lambda函数)
什么是匿名函数 匿名函数(也称为lambda函数)是Python中的一种小型匿名函数,它可以接受任意数量的参数,但只能有一个表达式。 语法格式: lambda arguments: expression使用场景 简单函数逻辑:当函数逻辑…...
java高并发------守护线程Daemon Thread
文章目录 1.概念2.生命周期与行为2. 应用场景3. 示例代码4. 注意事项 1.概念 Daemon : 滴门 在Java中,线程分为两类:用户线程(User Thread)和守护线程(Daemon Thread)。 守护线程是后台线程,主要服务于用户线程,当所…...
RocketMQ初认识
ProducerCustomerNameServer: Broker的注册服务发现中心BrokerServer:主要负责消息的存储、投递和查询以及服务高可用保证 RocketMQ的集群部署: 单个master的分支多个Master 模式:集群中有多个 Master 节点,彼此之间相互独立。生产者可以将消…...
K8s的BackUP备份
文章目录 1、kubeadm 安装的单 master 节点数据备份和恢复方式2、Velero 工具3、Velero 服务部署4、备份还原数据 ETCD备份/还原有多种类型,取决于你 k8s 集群的搭建方式 1、kubeadm 安装的单 master 节点数据备份和恢复方式 拷贝 etcdctl 至 master 节点…...
Photoshop 快捷键指南
Photoshop 快捷键指南 放大缩小 按住 Ctrl 鼠标滚轮快捷键 Z 鼠标左键往左往右Ctrl 放大, Ctrl - 缩小 套索工具 快捷键 L鼠标左键绘制按住 ctrl,松开鼠标左键,继续绘制直线绘制完成之后,按住ctrl,鼠标左键继续绘…...
Openlayers:海量图形渲染之图片渲染
最近由于在工作中涉及到了海量图形渲染的问题,因此我开始研究相关的解决方案。在这个过程中我阅读了文章 《Openlayers海量矢量面渲染优化》了解到了利用Canvas在前端生成图片渲染的思路,后来我又从同事那里了解到了后端生成图片渲染的思路。我认为这两种…...
自定义组件触发饿了么表单校验
饿了么的表单控件,如果存在自定义组件更改了值,例如在el-from中存在原生input组件很有可能没法触发表单校验,下拉框或者弹框组件仍然是报红边框。 这是因为饿了么的输入框或者下拉框更改值的时候会自动触发表单校验,但是封装过后的…...
【C++】从零实现Json-Rpc框架(1)
目录 一、项目介绍 二、技术选型 1. RPC的实现方案: 2. 网络传输的参数和返回值怎么映射到对应的RPC 接口上? 3. 网络传输怎么做? 4. 序列化和反序列化? 三、开发环境 四、环境搭建 Ubuntu-22.04 环境搭建 项目汇总&…...
[实战] linux驱动框架与驱动开发实战
linux驱动框架与驱动开发实战 Linux驱动框架与驱动开发实战一、Linux驱动框架概述1.1 Linux驱动的分类1.2 Linux驱动的基本框架 二、Linux驱动关键API详解2.1 模块相关API2.2 字符设备驱动API2.3 内存管理API2.4 中断处理API2.5 PCI设备驱动API 三、Xilinx XDMA驱动开发详解3.1…...
【详细】MySQL 8 安装解压即用 (包含MySQL 5 卸载)
卸载MySQL 1.卸载 2.安装目录删除残余文件(当初安装的位置) 3.删除programData下面的mysql数据文件 4.检查mysql服务是否存在,如果存在则删除(先暂停mysql服务) sc delete mysql 5.删除注册表中残留信息 安装MySQL 8&…...
Linux:(五种IO模型)
目录 一、对IO的重新认识 二、IO的五种模型 1.阻塞IO 2.非阻塞IO 3.信号驱动IO 4.IO多路转接 5.异步IO 6.一些概念的解释 三、非阻塞IO的代码实现 1.fcntl 2.实现主程序 一、对IO的重新认识 如果有人问你IO是什么,你该怎么回答呢? 你可能会说…...
初识数据结构——Java包装类与泛型:从入门到源码解析
【深入浅出】Java包装类与泛型:从入门到源码解析 🌟 一、开篇一问:为什么我们需要包装类? Java作为一门"面向对象"的语言,却保留了8个"非对象"的基本数据类型(有传言说,是…...
【计算机网络】Linux配置SNAT策略
什么是NAT? NAT 全称是 Network Address Translation(网络地址转换),是一个用来在多个设备共享一个公网 IP上网的技术。 NAT 的核心作用:将一个网络中的私有 IP 地址,转换为公网 IP 地址,从而…...
与 AI 共舞:解锁自我提升的无限可能
与 AI 共舞:解锁自我提升的无限可能 在数字化浪潮的汹涌冲击下,人工智能(AI)正以前所未有的速度重塑着世界的每一个角落。从日常生活的点滴便利到复杂工作的高效推进,AI 的力量无处不在。然而,面对 AI 的强…...
Android学习总结之算法篇五(字符串)
字符串求回文字串数目 public class CountPalindromicSubstrings {/*** 此方法用于计算字符串中回文子串的数量* param s 输入的字符串* return 回文子串的数量*/public static int countSubstrings(String s) {// 若输入字符串为空或长度为 0,直接返回 0if (s nu…...
使用人车关系核验API快速核验车辆一致性
一、 引言 随着车辆交易的日益频繁,二手车市场和金融领域的汽车抵押业务蓬勃发展。然而,欺诈和盗窃行为也时有发生,给行业带来了不小的冲击。例如,3月20日央视曝光的“新能源车虚假租赁骗补”产业链,以及某共享汽车平…...
day 8 TIM定时器
一、STM32 定时器概述 1. 定时器的概述定时器的基本功能,但是 STM32 的定时器除了具有定时功能之外,也具有定时器中断功能,还具有输入捕获(检测外部信号)以及输出比较功能(输出不同的脉冲)&…...
硬币找零问题
硬币找零问题:假设需要找零的金额为C,最少要用多少面值为p1<p2<…<pn的硬币(面值种类为n,且假设每种面值的硬币都足够多)? 贪心算法的基本原理是:遵循某种既定原则,不断…...
【微机及接口技术】- 第四章 内部存储器及其接口(上)
文章目录 第一节一、存储器的分类二、存储器的层次结构 第二节 半导体存储器一、半导体存储器的基本结构二、半导体存储器的分类1. 只读存储器 ROM2. 随机存储器 RAM 三、内存的主要性能指标1. 存储容量2. 存取时间3. 存取周期4. 可靠性5. 性价比 四、典型的半导体存储器芯片 本…...
tomcat的web三大组件Sciidea搭建web/maven的tomcat项目
文章目录 1. web项目的搭建1. 创建web项目2.修改web.xml版本3.添加servlet、jsp依赖4.servlet示例(使用注解)5.配置tomcat6.添加artifact7.部署8.启动tomcat、访问9.打war包10.部署到tomcat 2.maven的项目搭建1.创建项目图解 2.tomcat启动方式图解idea打…...
《SQL赋能人工智能:解锁特征工程的隐秘力量》
在当今的科技发展进程中,人工智能(AI)已经成为推动各领域变革的核心驱动力。而在人工智能的庞大体系里,特征工程占据着举足轻重的地位,它是将原始数据转化为能够让模型有效学习的特征的关键环节。鲜有人深入探讨的是&a…...
SQLmap工具使用
1. sqlmap介绍 sqlmap是一款自动化的SQL注入工具,用于检测和利用web应用程序中的SQL注入漏洞。不需要我们进行手注,当我们输入url地址后,会自动进行注入指令并将payload返回显示。 在kali中自带。在本机中需要下载,在相应的路径…...
Kubernetes集群管理详解:从入门到精通
1. 引言 Kubernetes(简称k8s)作为当今最流行的容器编排平台,已成为云原生应用部署和管理的事实标准。本文将深入探讨k8s集群管理的各个方面,为运维工程师和开发人员提供一个全面的指南。 2. Kubernetes架构概览 在深入具体的管理任务之前,让我们先回顾一下Kubernetes的基本架…...
【含文档+PPT+源码】基于Python的全国景区数据分析以及可视化实现
项目介绍 本课程演示的是一款基于Python的全国景区数据分析以及可视化实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 带你从零开始部署运行本套系统 该…...
鸿蒙开发者高级认证编程题库
题目一:跨设备分布式数据同步 需求描述 开发一个分布式待办事项应用,要求: 手机与平板登录同一华为账号时,自动同步任务列表任一设备修改任务状态(完成/删除),另一设备实时更新任务数据在设备离线时能本地存储,联网后自动同步实现方案 // 1. 定义分布式数据模型 imp…...
【网络安全】安全的网络设计
网络设计是网络安全的基础,一个好的网络设计可以有效的防止攻击者的入侵。在本篇文章中,我们将详细介绍如何设计一个安全的网络,包括网络架构,网络设备,网络策略,以及如何处理网络安全事件。 一、网络架构…...
基于FLask的重庆市造价工程信息数据可视化分析系统
【FLask】基于FLask的重庆市造价工程信息数据可视化分析系统 (完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 在当今快速发展的建筑工程行业中,造价信息的准确性和时效性对于项目决…...
swift-08-属性、汇编分析inout本质
一、Swift中跟实例相关的属性可以分为2大类 1.1 存储属性( Stored Property) 类似于成员变量这个概念 存储在实例的内存中 结构体、类可以定义存储属性 枚举不可以定义存储属性(因为枚举只存储关联值和case) 1.2 计算属性&am…...
Java 大视界 -- Java 大数据在智能医疗远程护理与患者健康管理中的应用与前景(175)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
大数据技术发展与应用趋势分析
大数据技术发展与应用趋势分析 文章目录 大数据技术发展与应用趋势分析1. 大数据概述2 大数据技术架构2.1 数据采集层2.2 数据存储层2.3 数据处理层2.4 数据分析层 3 大数据发展趋势3.1 AI驱动的分析与自动化3.2 隐私保护分析技术3.3 混合云架构的普及3.4 数据网格架构3.5 量子…...
如何在Ubuntu上安装Dify
如何在Ubuntu上安装Dify 如何在Ubuntu上安装docker 使用apt安装 # Add Dockers official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg…...
ffmpeg音频分析
对一个16k 单声道音频,生成频谱图 ./ffmpeg -i input.wav -lavfi "showspectrumpics800x400:modecombined:scalelin:gain1.5" spectrum.png...
每天五分钟深度学习框架pytorch:搭建LSTM完成手写字体识别任务?
本文重点 前面我们学习了LSTM的搭建,我们也学习过很多卷积神经网络关于手写字体的识别,本文我们使用LSTM来完成手写字体的识别。 网络模型的搭建 class RNN(nn.Module):def __init__(self,in_dim,hidden_dim,n_layer,n_class):super(RNN,self).__init__()self.n_layer=n_la…...
Maven工具学习使用(七)——Maven属性
内置属性 主要有两个常用的属性${basedir}表示项目的根目录,即包含pom.xml文件的目录;$[version]表示项目版本。 POM属性 使用该类属性引用POM文件中对应元素的值。例如${project.artifactId}就对应了元素的值,常用的POM属性包括: ${project.build.sourceDirectory} 项…...
【Linux网络与网络编程】05.应用层自定义协议序列化和反序列化
前言 本篇博客通过网络计算器的实现来帮助各位理解应用层自定义协议以及序列化和反序列化。 一、认识自定义协议&&序列化和反序列化 我们程序员写的一个个解决我们实际问题,满足我们日常需求的网络程序都是在应用层。前面我们说到:协议是一种…...
搭建K8S-1.23
0、简介 这里只用3台服务器来做一个简单的集群 地址主机名192.168.160.40kuber-master-1192.168.160.41kuber-master-2192.168.160.42kuber-node-1 1、关闭三个服务 (1)防火墙 systemctl stop firewalld (2)Selinux setenf…...
解决Spring Boot Test中的ByteBuddy类缺失问题
目录 解决Spring Boot Test中的ByteBuddy类缺失问题前奏问题描述问题解决第一步:移除ByteBuddy的特定版本号第二步:更新maven-surefire-plugin配置第三步:清理并重新构建项目 结语 解决Spring Boot Test中的ByteBuddy类缺失问题 前奏 今天&…...
npm 项目命名规则
以下是 npm 项目命名规则的详细说明: 一、核心命名规则 必须使用小写字母 名称中不能包含大写字母。原因: 跨平台兼容性(如 Linux 区分大小写,而 Windows 不区分)。避免命令行和 URL 中的大小写冲突(例如包…...
#SVA语法滴水穿石# (012)关于 first_match、throughout、within 的用法
我们今天学习, SystemVerilog 断言(SVA)中 first_match、throughout、within 运算符。 1. first_match 定义与作用 功能:在可能产生 多个匹配结果 的复合序列(如 or 或重复操作符)中,仅选择第…...
基于springboot+vue的二手车交易系统
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...
洛谷P11999.投入严厉地本地
洛谷P11999.投入严厉地本地 题目 题目解析及思路 题目要求根据两个字符串s和t,反推出一个映射集合f,其中s的每一个长度为k的子串都可以映射成单个字符或空字符 算出最终映射集合有多少个空字符,用全排列函数去搜索所有情况,判断…...
低代码开发平台:飞帆中新增控件、修改他人控件
飞帆是一个自由的控件平台。所有的网页都由控件搭建而成。 在我的资源、我的控件中,点击新增可以新增控件 对于他人的控件,点击复制控件展开,点击复制到我的控件 飞帆中的控件是使用 Vue2 来实现的...
Openstack指南
什么是云计算 概念 云计算是一种基于互联网的计算方式,通过这种方式,共享的软硬件资源和信息,可以按需求提供给计算机和其他设备。用户不需要了解”云“中的基础设施细节,不必具有相应的专业知识,也无需直接控制。云…...
[自制调试工具]构建高效调试利器:Debugger 类详解
一、引言 在软件开发的漫漫征程中,调试就像是一位忠诚的伙伴,时刻陪伴着开发者解决代码里的各类问题。为了能更清晰地了解程序运行时变量的状态,我们常常需要输出各种变量的值。而 Debugger 类就像是一个贴心的调试助手,它能帮我…...
【网络IP】原生IP是什么?如何获取海外原生IP?
一、什么是原生IP 原生IP地址是互联网服务提供商(ISP)直接分配给用户的真实IP地址,无需代理或转发。这类IP的注册国家与IP所在服务器的注册地相符。这种IP地址直接与用户的设备或网络关联,不会被任何中间服务器或代理转发或隐藏。…...