C++对C的扩充

C++既可用于面向过程的程序设计,也可用于面向对象的程序设计。在面向过程程序设计的领域,C++继承了C语言提供的绝大部分功能和语法规定,并在此基础上做了不少扩充,主要有一下几个方面:

1.C++的输入输出

C++为了方便用户,除了可以利用scanf和printf函数进行输入输出外,还增加了标准输入输出流cout和cin。它们在头文件iostream中定义的。

1.1用cout进行输出

cout必须和输出运算符“<<”一起使用。下面给出一个简单的cout输出语句。

#include <iostream>
using namespace std;int main()
{int a = 10;cout << a << endl;//printf("%d\n",a);return 0;
}

cout输出语句与下面的printf函数语句时等价的,endl就相当于'\n'。

利用cout输出数据的时候每输出一项就得用一个“<<”。不能写成“cout<<a,b,c<<endl;”。

使用cout进行输出的时候不用进行格式化输出,即不用"%d"这种的格式化输出,cout会自动查询待输出的数据的类型。所以利用cout输出数据比printf简单。

如果要在屏幕上输出一句话,或者提示信息,要在<<中加上双引号。

如果要指定输出所占的列数,可以用控制符setw进行设置,入setw(5)的作用时为其后面一个输出项预留5列的空间,如果输入出数据项长度不足5列,则数据向右对其,若超过5列则按实际长度输出。说明使用setw,应在程序的开头包含头文件<iomanip>或者<iomanip.h>。 

数据的输出默认是右对齐,如果向修改为左对齐就得使用'left': 

使用left可以使下一个待输出的数据以左对齐的方式输出。 使用left也要包含头文件<iomanip>或者<iomanip.h>。

1.2用cin进行输入

从输入设备向内存流动的数据流称为输入流。cin可以实现从标准设备的输入操作,它的功能与scanf函数相同。使用cin必须得和”>>“运算符一起使用。该运算符从输入设备获取数据并送到输入流cin中,然后再送到内存中。”>>“常称为”提取运算符“。现在给出简单的输入例子:

int main()
{int a = 0;cin >> a;//scanf("%d",&a);cout << a << endl;return 0;
}

我们可以看到cin与scanf相比,书写更为简单。与cout相同,cin在输入数据时不用指定数据的类型,系统会自动识别该变量的类型。一次输入多个数据时,不要写在一块,要分开写,输入一个后,以空格作为分割,在输入下一个:

2.用const定义常变量 

在C语言中经常利用#define来定义符号常量,如:#define max 1000

实际上,这种方式只是在预编译时进行字符替换,即将所有的max都替换为100.但是这种方式定义的常量没有类型检查,而且很容易发生意想不到的错误。

而在C++中提出了用const来定义常量。

const int a = 10;

上面就是利用const定义了一个常变量。它实际上还是一个变量,有数据类型,占用储存单元,有地址,可以用指针指向它,只是在程序运行期间该变量的值时固定的,不能被修改。

我们看,我们已经定义a为常变量,a的值就不能在被修改,此时a = 12,就是非法的,会使程序报错。 

3.函数原型声明

我们在调用函数的时候,如果被调函数定义在被调到位置之后,C++强制要对该函数进行声明。这样做的目的是使编译系统对函数调用的合法性进行检查,尽量保证程序的正确性。

上面的max函数的调用就在定义之前,所以我们在使用之前要对其进行声明。 函数声明的一般形式为:

函数类型 函数名 (参数表);参数表既可以包含类型和参数名,也可以只包含参数类型。如:下面两种写法等价:

int max (int x,int y); int max(int ,int)。

但是每次都对函数进行声明之前很麻烦,所以我们在写函数定义的时候,就直接将定义写在调用该函数之前,这样就不必在进行函数声明了。

4.函数的重载 

在前面的程序中用到了插入运算符"<<"和提取运算符">>"。这两个运算符原本是C和C++位运算中的左移运算符和右移运算符,现在C++又把它作为输入输出运算符。允许一个运算符可以用于不同场合,不同的场合有不同的含义,这就叫做运算符的重载,即重新赋予它新的含义。其实就是”一物多用“。

在C++中函数也可以重载。我们在C语言编程的时候,我们会发现有几个不同名的函数进行的时同一类的操作。例如:找出两个整数的最大值,找出两个浮点数的最大值,找出两个字符的最大值。

我们在用C语言实现该方法时,要写三个不同的函数:

int max1(int x, int y);
float max2(float x, float y);
char max3(char x, char y);

但是我们知道这三个函数内部的代码是相同的,不同的只是函数的参数和返回值。而C++提出了函数重载的概念就可以很方便的解决该问题。

我们可以将这三个函数的函数名统一为max,然后我们调用max函数时到底调用的是哪一个max是由你传的参数决定的。如果你传的是整型,则调用整型max函数,如果你传的是char,则调用字符max函数。

C++允许在同一作用域中用同一函数名定义多个函数,这些函数的参数个数和参数类型不同,这些同名函数用来实现不同的功能。这就是函数的重载,即一个函数名多用。 

注意:重载函数的参数个数或参数类型至少有一个不同,即要不参数个数相同而参数类型不同,要不参数类型相同参数个数不同,要不两者都不同。函数的返回值可以相同也可以不同。 不允许参数个数和参数类型都相同而只有返回值不同,因为系统无法从函数的调用形式上判断那一个函数与之匹配。

下面给出一个函数重载的例子:利用函数重载实现求两个整数以及三个整数的最大值。

#include <iostream>
#include <iomanip>
using namespace std;int max(int x, int y)
{return x > y ? x : y;
}int max(int x, int y, int z)
{if (x < y){x = y;}if (x < z){x = z;}return z;
}int main()
{int a = 1;int b = 2;int c = 3;cout << max(a, b) << endl;cout << max(a, b, c) << endl;return 0;
}

上面的函数重载就体现了参数个数不同而参数类型和返回值类型相同。系统会根据你传递参数的个数,来判断该调用那一个函数。

5.函数模板 

我们刚才介绍了函数重载可以实现一个函数名多用,将实现相同或类型功能的函数用同一个函数名来定义。这样是编程者在调用同类函数是感觉到含义清楚,方法简单。但是在程序中仍然要分别定义每一个函数,就像刚才说过的求两个整型,浮点型,字符型的数据的最大值,它们的函数体是完全相同的,区别只在于返回值和参数类型的不同。

于是C++有提出了一个新的概念——函数模板。   

所谓函数模板,实际上就是建立一个通用的函数,其函数的返回值和参数类型是没有指定的,用一个虚拟的类型代表,这个通用的函数就叫做函数模板。凡是函数体相同的函数都可以用该函数模板来代替,不必再定义多个函数,只须再模板中定义一次即可。再调用该模板函数的时候,系统会根据实参的类型,将虚拟类型替换为实参的类型,实现了不同函数的功能。

下面将求两个数的最大值用函数模板实现:

#include <iostream>
#include <iomanip>
using namespace std;template<typename T>
T tmax(T x, T y)
{return x > y ? x : y;
}int main()
{int a = 1;int b = 2;float c = 1.2f;float d = 3.2f;char e = 'a';char f = 'x';cout << tmax(a, b) << endl;cout << tmax(c,d) << endl;cout << tmax(e,f) << endl;return 0;
}

下面就是定义的函数模板,T就是虚拟类型,他会在函数调用的时候由实参的类型来确定。 

template<typename T>
T tmax(T x, T y)
{return x > y ? x : y;
}

当我们传给该函数两个整型时,相当于函数变成了:

int max(int x, int y)
{return x > y ? x : y;
}

定义函数模板的一般形式为:

template<typename T>

函数体

或者

template<class T>

函数体

template的含义是”模板“,尖括号中先写关键字typename(或class)后面跟一个类型参数T,这个类型参数实际上是一个虚拟的类型名,表示模板中出现的T都只是一个类型而已,但是现在并没有指定他具体是哪一种类型,等到函数调用的时候,由实参的类型来决定。T只是一个标识符而已,也可以采用其他的。

class与typename的作用相同,都是表示”类型名“,而这可以互换。但因为class容易与C++中的‘类’搞混,所以建议使用typename来表示类型名。

类型参数可以不止一个,根据需要确定个数:

template<typename T1,typename T2>

 可以看到,用函数模板比函数重载更方便,程序更简洁。但应注意它只适用于函数的参数个数相同而类型不同,且函数体相同的情况,如果参数个数不相同,则不能用函数模板。

6.有默认参数的函数 

一般情况下,在函数调用时形参从实参那里得到值,因此实参的个数应与形参相同。而在有时多次调用同一函数时使用了同样的实参,C++提供了简单的处理办法,给形参一个默认值,这样形参就不必一定要从实参那里取值了。如:

float V(float r = 6.53);

即,指定r的默认值为6.53。如果调用该函数时,想使用默认值,则在调用该函数时,不必传参数。如:

float V(float r = 6.53);int main()
{V();//r = 6.53return 0;
}

此时,r的值就为默认值6.53.如果不想使用默认值,而需要自己给值的话,只需将需要的值传给该函数即可。如:

float V(float r = 6.53);int main()
{V(1.2);//r = 1.2return 0;
}

如果有多个形参,可以使每一个形参都有一个默认值,也可以只使一部分由默认值。例如由一个求圆柱体的体积的函数,形参h为高,r为底面半径。函数原型如下:

float V(float h,float r = 6.53);

该函数即默认该圆柱体的底面半径为6.53。该函数的调用有以下两种方式:

V(32.1);//h为32.1,r为默认值6.53V(32.1, 12.1);//h为32.1,r为12.1

实参与形参的结合是从左向右按顺序进行的,第一个实参必然与第一个形参结合,第二个实参必然与第二个形参结合……因此指定默认值的参数必须放在形参表列的最右端,否则会出错。

void f1(int x, int y, int z = 0, int n);//错误
void f2(int x,int y,int n,int z = 0)//正确

那么为什么会出错呢?如果我们想让x为1,y为2,z就为默认值0,n为3,那么我们要怎么传参呢?

f1(1, 2, 3);我们想这样调用,但是其实这时候z的值不是默认值而是3了,n没有值。所以当我们将带有默认值的形参没有放在形参表列的最右端时,就会在传参时造成歧义。

在使用带有默认参数的函数时有两点要注意:

  • 必须在函数调用之前将默认值的信息通知给编译系统。如果在声明函数时已对形参给出了默认值,而在定义函数是又对形参给出默认值,有的编译系统会给出”重复指定默认值“的报错信息,有的编译器对此不报错,甚至允许在声明时和定义时的默认值不同,此时由编译器先遇到谁为准。为了避免混淆,最好只在函数声明时指定默认值。
  • 一个函数不能既作为重载函数,有作为有默认参数的函数。因为在当函数调用时,如果少写了一个参数,系统不知道使利用重载函数还是利用默认参数的函数,会出现歧义。

例如:int max(int a,int b,int c = 100);

int max(int a,int b);

如果调用时为max(12,22);,编译系统无法知道是调用两个参数的max函数,还是调用带有默认值的函数。

7.变量的引用

变量的引用时C++对c的一个重要补充。

7.1引用的概念

在C++中,变量的“引用”其实就是变量的别名,因此引用又称别名。建立引用的作用是为变量再取一个新的名字,以便在需要时可以方便、间接的引用该变量。当你给一个变量起了一个别名之后,就相当与这个变量有个两个名字,你不管引用哪一个名字都可以对该变量进行修改。例如,有一个变量a,你要给它起一个别名:

int a = 10;
int& b = a;//声明b是整型变量a的引用

经过这样的声明之后,使用a和b的作用是相同的,都代表同一个变量。对任何一个修改,另一个也会发生改变。

我们给a起了一个别名b之后,将b修改了,a也会修改,因为两者对应着同一块内存空间。 

注意:

上述声明中,'&'是引用声明符,而不是取地址操作符。

对变量声明一个引用,并不开辟内存单元,b和a代表的同一块内存单元。

我们调试发现两者确实代表着相同的内存单元。

在声明一个引用的时候,必须同时是指初始化,即声明它代表哪一个变量。 

一个引用不能作为两个变量的别名。

在上图中,c既作为a的别名又作为b的别名,这是不允许的。一个引用只能作为一个变量的别名。

7.2引用的简单使用 

我们声明了b是变量a的引用,我们对a进行修改,a和b会同步发生变化,对b进行修改,a和b也会同时发生变化。 

7.3关于引用的简单说明

  • 引用并不是一种独立的数据类型,它必须与某一种类型的数据相联系。声明引用时必须指定它代表的是哪一个变量,即对它进行初始化。
int a = 10;
int& b = a;//正确,声明b是a的引用,即b是变量a的一个别名
int& b;//错误,没有指定b代表那个变量float c = 1.1;
int& d = c;//错误,声明b是一个整形变量的别名,但是却让它代表了浮点型变量c
  • 引用与其所代表的变量共享同一块内存单元,系统并不为引用另外分配储存空间。实际上,编译系统是引用和其代表的变量具有相同的地址。

我们打印他们的地址,的确是相同的。注意,cout里面的'&'是取地址操作符,而不是引用声明符。

  • 如果该&a前面有类型名,即(int & a),则必然是对引用的声明;如果前面没有类型名即(p = &a),此时的'&'是取地址运算符。
  • 对引用的初始化,可以用变量名,也可以用另外一个引用。 
int a = 10;
int& b = a;
int& c = b;

b是a的别名,c是b的别名,那c也就是a的别名。

  • 引用在初始化为某一个变量的别名之后,不能再被重新声明为另一个变量的别名。 

7.4将引用作为函数参数

 将引用作为函数参数的最用类似于指针的作用。假如我们要写一个函数用来交换两个变量,C语言中我们通过传该变量的地址来修改。现在我们可以通过引用来实现这个功能,不必再传地址。

void swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}int main()
{int a = 10;int b = 99;cout << "a = " << a << " " << "b = " << b << endl;swap(a, b);cout << "a = " << a << " " << "b = " << b << endl;return 0;
}

我们看到,我们利用变量的引用也可以是实现两个变量的交换。我们设置函数的时候形参表设为某个变量的引用。但是此时并没有进行初始化,当我们将实参ab传过去的时候,swap中的a就成了实参a的别名,b成了实参b的别名。而我们前面知道了别名和变量指的是同一块内存,所以我们将别名交换了,实参本身也就交换了。

实际上,实参传给形参的是实参的地址,也就是使形参a和实参a具有同样的地址,从而是两者共用同一块内存单元。 

7.4.1使用引用和使用指针变量作为函数参数有什么不同?

  • 不必再swap函数中设立指针变量,指针变量要另外开辟内存单元,其内容是地址。而引用不是一个独立的变量,不单独站内存单元。
  • 在main函数中调用swap函数值,实参不必在变量名前加'&'以表示地址。系统传送的是实参的地址,二部制实参的值。
  • 在使用指针变量的时候要对其进行解引用操作。而使用引用时,引用就代表了该变量,不必解引用。
  • 用引用能完成的工作,用指针也能完成。但用引用比用指针直观,方便,直截了当。

7.5对引用的进一步说明 

7.5.1不能建立void类型的引用。

任何实际存在的变量都是有具体类型的。而我们在声明引用的时候就要完成初始化,所以此时已经知道了引用的类型。

7.5.2不能建立引用的数组

char a[4] = "abcd";
char& r[4] = c;//错误

数组名c只代表首元素的地址,本身并不是一个占有存储空间的变量。

7.5.3可以将变量的引用的地址赋给一个指针变量,此时指针指向的是原来的变量

int a = 3;
int& b = a;
int* p = &b;

此时a.b.*p指向的是同一块内存,都代表了a变量。

但是不能定义指向引用类型的指针变量,不能写成

int&* p = &a;

由于引用不是一种独立的数据类型,因此不能建立指向引用类型的指针变量。

7.5.4可以建立指向指针类型的引用

int i = 1;
int* p = &i;
int*& pr = p;

pr先与'&'结合,说明pr是一个引用,指向的是一个int* 类型的变量。所以此时引用pr也相当于一个指针变量了,指向的是i。此时*pr的值,就相当于*p的值,就是i的值。

7.5.5可以用const对引用加以限定,不允许改变该引用的值。

int main()
{int a = 14;const int& b = a;//用const修饰的引用不能被修改b = 1;//错误a = 1;//但是可以直接改变变量本身return 0;
}

此时输出a和b的值,都是1。

7.5.6可以用常量或表达式对引用进行初始化,但此时必须用const声明。

如:

int i = 5;
const int& a = i + 3;

8.内置函数

调用函数时需要一定的时间,如果有些函数需要频繁的使用,则累计所用时间会很长,从而降低程序的执行效率。C++提供一种提高效率的方法,即在编译时将所调用的函数的代码嵌入到主调函数中。这种嵌入主调函数中的函数称为内置函数,又称内嵌函数或者内联函数

指定内置函数只需在函数首行的左端加上关键字inline即可。

例:将比较两个数的大小写成内置函数。

inline int max(int x, int y)
{return x > y ? x : y;
}int main()
{int a = 1;int b = 2;int c = max(a, b);cout << c << endl;return 0;
}

将max作为内联函数后,在编译的时候,系统会将主函数中的max展开如下:

int main()
{int a = 1;int b = 2;int c = 0;x = a;y = b;c = x > y ? x : y;c = max(a, b);cout << c << endl;return 0;
}

使用内置函数可以节省运行时间,但却增加了目标程序的长度。假设要调用10次max函数,则在编译时先后10次将max的代码复制并插入main函数中,大大增加了main函数的长度。因此只有对规模很小且使用频繁的函数,才可大大提高运行速度。

9.作用域运算符

每一个变量都有其有效的作用域,只能在变量的作用域内使用该变量,不能直接使用其他作用域1中的变量。

假如有一个全局变量a为浮点型,main函数中也有一个a为整型,当我们在主函数中打印a时,将会打印整型a,而不是浮点型a。因为,在main函数中,局部变量将屏蔽全局变量。

那如果我们就是想打印浮点型的a呢?

C++提供作用域运算符“::”,它能只当所需要的作用域。

float a = 1.1;int main()
{int a = 10;cout << a << " " << ::a << endl;return 0;
}

"::"表示全局作用域中的变量a。请注意:不能用“::”访问函数中的局部变量。

10.字符串变量 

C++提供了一种新的类型——字符串类型(string),可以用此来定义字符串变量。

实际上,string并不是C++语言本身具有的基本类型(而int char double float等是C++本身提供的基本类型),它是在C++标准库中声明的一个字符串类,用这种类可以定义字符串变量。

10.1定义字符串变量

我们可以按照定义int类型等方式来定义字符串变量。

string s1;
string s2 = "china";

应当注意:定义string类字符串变量要包含头文件<string>。注意不是<string.h>。

10.2对字符串变量进行赋值

如:

string s1 = "china";

既可以用一个字符串常量给字符串变量赋值,也可以用另一个字符串变量对其赋值。

string s1;
string s2 = "china";
s1 = s2;//s1的内容也是"china"

这样赋值不要求s1和s2的长度相同。字符串变量的长度会根据其中的内容而改变。

string s1 = "ab";
string s2 = "china";
s2 = s1;//s2变成了ab

可以对字符串变量中某一个字符进行操作,如:

string word = "she";
word[2] = 'a';//此时word的内容为"sha"

需要注意的是,字符串常量以'\0'结尾,但是当把其赋给字符串变量的时候,字符串变量不会存储'\0'。因此上面的word变量中只有三个字符,而不包括'\0'。

10.3字符串变量的输入输出

可以通过cin和cout对string字符串变量进行输入输出操作。

int main()
{string s1;string s2;cin >> s1 >> s2;cout << s1 << s2 << endl;return 0;
}

10.4字符串变量的运算

在以字符数组存放字符串时,字符串的运算要通过字符串函数,如strcat(连接)、strcmp(比较)、strcpy(复制),而对string类对象,可以使用更简单的运算符。

10.4.1字符串复制用赋值号

str1 = str2;

10.4.2两字符串连接用+号

string s1 = "hello";
string s2 = "world";
s1 = s1 + s2;//连接s1和s2,s1 = "helloworld"

10.4.3字符串比较直接使用关系运算符

可以直接用 == < > <= >=等关系运算符来比较字符串。

10.5字符串数组

不仅可以用string定义字符串变量,也可以定义字符串数组。

string str[3] = { "zhangsan","lisi","wangwu" };

此时,str字符串数组的内部情况:

我们可以看到:

  • 这个字符串数组包含三个元素,每个元素都是一个字符串变量
  • 字符串数组不要求每个元素长度相同,长度会随着赋给它的值而改变
  • 字符串数组的每一个元素存放一个字符串变量,而不是一个字符
  • 没有一个字符串元素都不包含'\0',只包含自己本身。

其实之所以会出现这种情况是因为字符串数组存放的其实是每一个字符串变量的首地址。

11.动态分配/撤销内存的运算符new和delete

在C语言中我们进行动态内存管理常用到malloc、realloc、calloc以及free这几个函数。

C++提供了较简便而功能性较强的运算符nwe和delete来取代mallco以及free函数。例如:

new int;//开辟一个整形的空间,返回一直指向整形数据的指针
new int(100);//开辟一个整形的空间,并指定该整数的初始值为100
new char[3];//开辟一个存放字符数组的空间,该空间可以存放3个字符,返回一个指向字符数据的指针
new int[5][4];//开辟一个二维数组

new运算符的一般格式为

new 类型[初值];用new分配数组空间时,不可以进行初始化。

delete运算符的一般格式为

delete []指针变量;

例如:撤销整型变量a,delete a;

撤销字符数组b,delete[]b;

注意:new和delete是运算符,不是函数,因此执行效率高。new和delete要配合使用。

完! 

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

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

相关文章

Spring 事务源码分析

前言&#xff1a; 我们知道 Spring 声明式事务是通过 AOP 来实现的&#xff0c;日常项目开发中我们只需要使用 Transactional 注解就可以实现声明式事务&#xff0c;那你知道通过 Transactional 注解怎样实现事务的吗&#xff1f;本篇我们将从源码来分析 Spring 声明式事务的执…

STM32定时器四大功能之定时器编码接口

1什么是编码器接口&#xff1f; 编码器接口接受编码器的正交信号&#xff0c;根据编码器产生的正交信号脉冲控制CNT的自增和自减&#xff0c;从而指示编码器的旋转方向和旋转速度。 每个高级定时器和通用定时器都有一个编码器接口&#xff0c;同时正交编码器产生的正交信号分…

Redis 的持久化(真的好细)

前言 Redis 是一个内存数据库&#xff0c;把数据存储在内存中&#xff0c;而内存中的数据是不持久的&#xff0c;要想数据持久就得将数据存储到硬盘中&#xff0c;而 Redis 相比于 Mysql 这样的关系型数据库最大的优势就在于将数据存储在内存中从而效率更高&#xff0c;速度更快…

docker 安装RabbitMQ-web版本

直接拉去web版本 docker pull rabbitmq:management启动命令 设置用户名 admin 密码123456 docker run -dit --name rabbitmq -p 5672:5672 -p 15672:15672 -e RABBITMQ_DEFAULT_USERadmin -e RABBITMQ_DEFAULT_PASS123456 rabbitmq:management访问地址 http://127.0.0.1:…

GeoScene产品学习视频收集

1、易智瑞运营的极思课堂https://www.geosceneonline.cn/learn/library 2、历年易智瑞技术公开课视频资料 链接&#xff1a;技术公开课-易智瑞信息技术有限公司&#xff0c;GIS/地理信息系统&#xff0c;空间分析-制图-位置智能-地图 3、一些关于GeoScene系列产品和技术操作的视…

二进制部署k8s集群 部署高可用master节点

目录 本次部署的环境 一、master02 节点部署 二、负载均衡部署 安装nginx服务 部署keepalive服务 修改node节点上的配置文件 在master节点上创建pod 三、部署 Dashboard 二进制部署k8s集群部署的步骤总结 &#xff08;1&#xff09;k8s的数据存储中中心的搭建 etcd &…

Apache Log4j Server 反序列化命令执行漏洞(CVE-2017-5645)

漏洞复现环境搭建请参考 http://t.csdnimg.cn/MxmId 漏洞版本 Apache Log4j 2.8.2之前的2.x版本 漏洞验证 &#xff08;1&#xff09;开放端口4712 漏洞利用 &#xff08;1&#xff09;ysoserial工具获取 wget https://github.com/frohoff/ysoserial/releases/download/v0…

Flink DataStream API 基础算子(一)

一、介绍 官网 DataStream API 得名于特殊的 DataStream 类&#xff0c;该类用于表示 Flink 程序中的数据集合。你可以认为 它们是可以包含重复项的不可变数据集合。这些数据可以是有界&#xff08;有限&#xff09;的&#xff0c;也可以是无界&#xff08;无限&#xff09;的…

spring启动后自动退出了

在项目中启动spring框架的application&#xff0c;但是还未等到接口访问它就自己退出了&#xff0c;运行截图如下所示&#xff1a; 解决办法&#xff1a; 将build.gradle文件里的依赖修改一下。我原先的依赖是&#xff1a; org.springframework:spring-web:5.3.10 现修改为 …

2024 电工杯高校数学建模竞赛(B题)| 平衡膳食食谱 |建模秘籍文章代码思路大全

铛铛&#xff01;小秘籍来咯&#xff01; 小秘籍团队独辟蹊径&#xff0c;运用负载均衡&#xff0c;多目标规划等强大工具&#xff0c;构建了这一题的详细解答哦&#xff01; 为大家量身打造创新解决方案。小秘籍团队&#xff0c;始终引领着建模问题求解的风潮。 抓紧小秘籍&am…

肯尼亚大坝决堤反思:强化大坝安全监测的必要性

一、背景介绍 近日&#xff0c;肯尼亚发生了一起严重的大坝决堤事件。当地时间4月29日&#xff0c;肯尼亚内罗毕以北的一座大坝决堤&#xff0c;冲毁房屋和车辆。当地官员称&#xff0c;事故遇难人数已升至71人。这起事件再次提醒我们&#xff0c;大坝安全无小事&#xff0c;监…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-23.1,2 讲 I2C驱动

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

了解区块链基础设施,共同构建安全且强大的Sui网络

区块链基础设施的范畴很广&#xff0c;但其核心是那些直接与网络互动的计算机。这些实体通常被称为节点&#xff0c;分为不同的类型&#xff0c;例如维护完整区块链副本的全节点&#xff0c;以及作为共识决定者的验证节点。除了这两种类型之外&#xff0c;还有其他类型的节点&a…

【oracle的安装记录】

oracle安装记录 一、下载以后&#xff0c;解压到同一路径下面 二、双击可执行安装文件&#xff0c;等待文件加载 三、双击以后&#xff0c;弹出信息 四、提示该窗口&#xff0c;点击【是】即可 五、未填写配置安全更新信息 六、弹出小窗口&#xff0c;选择【是】 七、安装选项…

SQLI-labs-第二十四关

目录 1、登录界面 2、注册界面 3、修改密码界面 知识点&#xff1a;二次注入 思路&#xff1a; 这一关有几个页面可以给我们输入&#xff0c;一个登录界面&#xff0c;一个注册页面&#xff0c;一个修改密码界面 1、登录界面 首先我们登录界面看看 登录后出现一个修改密码…

Ubuntu 搭建SRT协议 环境

1.官网clone源码 GitHub - Haivision/srt: Secure, Reliable, Transport 打不开的话国内gitee 不是最新的 https://gitee.com/smartavs/srt.git 下下来之后 cd 到srt目录 需要安装cmake openssl等依赖 我的环境已经有了 mkdir build && cd build cmake .. -…

最有效的企业数据防泄漏手段 | 数据泄漏防护系统推荐

随意信息安全意识不断提高&#xff0c;企业纷纷寻求高效的数据防泄漏手段。在众多解决方案中&#xff0c;这五款软件各具特色&#xff0c;但它们的共同目标都是确保企业数据的安全性和保密性。 接下来&#xff0c;我们将逐一介绍这五款软件的特点和优势。 1、Ping 32 Ping32…

前端项目使用docker编译发版和gitlab-cicd发版方式

项目目录 app/ ├── container/ │ ├── init.sh │ ├── nginx.conf.template ├── src/ ├── .gitlab-ci.yml └── deploy.sh └── Dockerfile └── Makefilecontainer目录是放nginx的配置文件&#xff0c;给nginx镜像使用 .gitlab-ci.yml和Makefile是c…

阿里云 EMR Serverless Spark 版开启免费公测

阿里云 EMR Serverless Spark 版是一款云原生&#xff0c;专为大规模数据处理和分析而设计的全托管 Serverless 产品。它为企业提供了一站式的数据平台服务&#xff0c;包括任务开发、调试、调度和运维等&#xff0c;极大地简化了数据处理的全生命周期工作流程。使用 EMR Serve…

LayUI使用(一)点击树组件的右边空白区域也可响应事件

前提&#xff1a; 如下&#xff0c;希望能够点击右边的空白区域也能够响应&#xff0c;而不仅仅是点击文本才响应 分析流程 一开始问了chatgpt&#xff0c;但它给的方案太麻烦了&#xff0c;而且还有错误&#xff0c;因此自己上手F12进入调试模式&#xff0c;点击查看最终渲…