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

C++复习笔记——primer第五版

文章目录

  • 一、引用和指针
    • 1.引用
    • 2.指针
      • 2.1利用指针访问对象
      • 2.2指针的值或指针所指对象的值的改变
    • 3.赋值和指针
    • 4.指向指针的引用
  • 二、String
    • 1.初始化String对象的方式
    • 2. string对象上的操作
    • 3.使用getline读取一整行
    • 4.字面值和字符串相加
    • 5.使用for循环改变字符串中的字符
  • 三、Vector
    • 1.定义和初始化vector对象
  • 四、迭代器
    • 标准容器迭代器的运算符
    • 迭代器的运算
  • 五、数组
    • 初始化
    • 理解复杂的数组声明
    • 数组和指针
  • 六、函数
    • 1.引用传递和值传递
    • 2.传值参数
      • 指针形参
        • 如何使用指针形参交换两个整数的值
    • 3.传引用参数
      • 使用引用避免拷贝。当函数无须修改引用形参的值时最好使用常量引用。
      • 使用形参隐式返回额外信息
    • 4.数组形参
    • 5.返回数组指针
      • 声明一个返回数组指针的函数
    • 6.函数重载
  • 七、类
    • 6.函数重载
  • 其他
    • Rvalue references 右值引用
    • 内存管理
  • 可变参数模板 Variadic Templates
    • 例一、可变模板参数(递归调用)
      • max函数比大小
      • 处理print函数
    • 例二、递归继承
    • 例三、递归复合

一、引用和指针

1.引用

​ 一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时,程序把引用和它的初始值绑定(bind)在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另外一个对象,因此引用必须初始化。
​ 引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字。
​ 定义了一个引用之后,对其进行的所有操作都是在与之绑定的对象上进行的:

refval = 2;		// 把2赋给 refVal 指向的对象,此处即是赋给了ival
int ii = refVal;//与ii=ival执行结果一样

2.指针

​ 指针(pointer)是“指向(point to)”另外一种类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。然而指针与引用相比又有很多不同点。其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。其二,指针无须在定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。

2.1利用指针访问对象

如果指针指向了一个对象,则允许使用解引用符(操作符*)来访问该对象

int ival = 42;
int *p = &ival;	//p存放着变量ival的地址,或者说p是指向变量ival的指针
cout << *p;		// 由符号*得到指针p所指的对象,输出 42

对指针解引用会得出所指的对象,因此如果给解引用的结果赋值,实际上也就是给指针既指的对象赋值:

*p = 0;			// 由符号*得到指针p所指的对象,即可经由P为变量ival赋值
cout << *p;		//输出0如上述程序所示,为*p赋值实际上是为p所指的对象赋值。
<!--解引用操作仅适用于那些确实指向了某个对象的有效指针。-->

2.2指针的值或指针所指对象的值的改变

​ 有时候要想搞清楚一条赋值语句到底是改变了指针的值还是改变了指针所指对象的值不太容易,最好的办法就是记住赋值永远改变的是等号左侧的对象。当写出如下语句时:

pi = &ival;  // pi 的值被改变,现在pi 指向了ival

​ 意思是为pi 赋一个新的值,也就是改变了那个存放在pi内的地址值。相反的,如果写出如下语句:

*pi = 0;		// ival的值被改变,指针pi并没有改变

​ 则*pi(也就是指针pi指向的那个对象)发生改变。

3.赋值和指针

​ 指针和引用都能提供对其他对象的间接访问,然而在具体实现细节上二者有很大不同,其中最重要的一点就是引用本身并非一个对象。一旦定义了引用,就无法令其再绑定到另外的对象,之后每次使用这个引用都是访问它最初绑定的那个对象
​ 指针和它存放的地址之间就没有这种限制了。和其他任何变量(只要不是引用)一样,
​ 给指针赋值就是令它存放一个新的地址,从而指向一个新的对象:

int i =42;
int *pi =0;		//pi被初始化,但没有指向任何对象
int *pi2 = &i;	//pi2被初始化,存有i的地址
int *pi3;		//如果pi3定义于块内,则pi3的值是无法确定的pi3= pi2;		//pi3和pi2指向同一个对象i
pi2 = 0;		//现在pi2不指向任何对象了

4.指向指针的引用

​ 引用本身不是一个对象,因此不能定义指向引用的指针。但指针是对象,所以存在
指向指针的引用:

int i=42;
int *pi ;		// p是一个int型指针
int *&r =pi;		//r是一个对指针p的引用r = &i;			//r引用了一个指针,因此给上赋值&i就是令p指向i
*r =0;			//解引用r得到i,也就是p指向的对象,将i的值改为0

​ 要理解r的类型到底是什么,最简单的办法是从右向左阅读r的定义。离变量名最近的符号(此例中是&r的符号&)对变量的类型有最直接的影响,因此r是一个引用。声明符的其余部分用以确定r引用的类型是什么,此例中的符号*说明r引用的是一个指针。最后,声明的基本数据类型部分指出r引用的是一个int指针。

二、String

1.初始化String对象的方式

string s1			//默认初始化,s1是一个字符串
string s2(s1)		//s2是s1的副本
string s2 == s1		//等价于上面
string s3("value")	//s3是字面值value的副本,除了最后一个空字符外
string s3 = "value"	//等价于上面
string s4(n,'c')	//n个连续的c组成的串

2. string对象上的操作

os<<s	//将s写到输出流os当中,返回os
is>>s	//从is中读取字符串赋给s,字符串以空白分隔,返回is
getline(is, s)//从is中读取一行赋给s,返回is
s.empty()	//s为空返回true,否则返回false
s.size()	//返回s中字符的个数
s[n]		//返回s中第n个字符的引用,位置n从0计起
s1+s2	//返回s1和s2连接后的结果
sl=s2	//用s2的副本代替s1中原来的字符
s1==s2	//如果s1和s2中所含的字符完全一样,则它们相等;string对象的相
s1!=s2	//等性判断对字母的大小写敏感
<<=>>=	//利用字符在字典中的顺序进行比较,且对字母的大小写敏感

​ 第1章曾经介绍过,使用标准库中的 iostream 来读写int、double等内置类型的值。同样,也可以使用IO操作符读写string对象:

//注意:要想编译下面的代码还需要适当的#include语句和using声明
int main()
{string s;cin >> s;			//如果程序的输入是“     Hello World!     "cout << s << endl;	//则输出将是“Hello”,输出结果中没有任何空格。return 0;    
}

string s1, s2;		// 把第一个输入读到 s1 中,第二个输入读到 s2 中
cin >> s1 >> s2;	//输出两个 string对象
cout << s1 << s2 << endl;//输出HelloWorld! 

3.使用getline读取一整行

​ 有时我们希望能在最终得到的字符串中保留输入时的空白符,这时应该用 getline函数代替原来的>>运算符。getline函数的参数是一个输入流和一个string对象,函数从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了),然后把所读的内容存入到那个string对象中去(注意不存换行符)。getline只要一遇到换行符就结束读取操作并返回结果,哪怕输入的一开始就是换行符也是如此。如果输入真的一开始就是换行符,那么所得的结果是个空string。
和输入运算符一样,getline 也会返回它的流参数。因此既然输入运算符能作为判断的条件(Ctrl+D/Z),我们也能用getline 的结果作为条件。例如,可以通过改写之前的程序让它一次输出一整行,而不再是每行输出一个词了:

int main()
{string line;	//每次读入一整行,直至到达文件末尾while (getline(cin, line))cout << line << endl;return 0;
}

​ 因为line中不包含换行符,所以我们手动地加上换行操作符。和往常一样,使用end1结束当前行并刷新显示缓冲区。

4.字面值和字符串相加

string s4 = s1 + ",";		//正确;把一个string对象和一个字面值相加
string s5 = "hello" + ",";	//错误;两个运算的对象都不是string
string s6 = s1 + "hello" + "," ;//正确;每个加法运算符都有一个string对象
string s7 = "hello" + "," + s1;	//错误;不能将两个字面值相加

5.使用for循环改变字符串中的字符

string s("Hello World!!!");//转换成大写形式。
for (auto &c :s)		// 对于s中的每个字符(注意:C是引用)c = toupper(c);		//c是一个引用,因此赋值语句将改变s中字符的值cout << s << endl;	

使用下标执行迭代
另一个例子是把s的第一个词改成大写形式:


//依次处理s中的字符直至我们处理完全部字符或者遇到一个空白
for (decltype(s.size())index =0; index != s.size() && !isspace(s[index]); ++index)s[index] = toupper(s[index]);		//将当前字符改成大写形式
//index的类型是由 decltype关键字决定的,保证下标小于size()的值就可以了。

三、Vector

1.定义和初始化vector对象

vector<T> vl		//v1是一个空vector,它潜在的元素是T类型的,执行默认初始化
vector<T> v2(v1)	//v2中包含有v1所有元素的副本
vector<T> v2 = vl	//等价于v2(v1),v2中包含有v1所有元素的副本
vector<T> v3(n, val)//v3包含了n个重复的元素,每个元素的值都是val 
vector<T> v4(n)		//v4包含了n个重复地执行了值初始化的对象
vector<T> v5{a,b,c.}	//v5包含了初始值个数的元素,每个元素被赋予相应的初始值
vector<T> v5 = {a,b, c.}	//等价于v5{a,b,c...}

四、迭代器

标准容器迭代器的运算符

*iter	返回迭代器iter所指元素的引用
iter->mem	解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
++iter	令iter指示容器中的下一个元素
--iter  令iter指示容器中的上一个元素
iterl == iter2		判断两个迭代器是否相等(不相等),如果两个迭代器指示的是同一个元
iterl != iter2		素或者它们是同一个容器的尾后迭代器,则相等;反之,不相等

​ 和指针类似,也能通过解引用迭代器来获取它所指示的元素,执行解引用的迭代器必须合法并确实指示着某个元素。试图解引用一个非法迭代器或者尾后迭代器都是未被定义的行为。

读取text文本数据:

// 依次输出 text 的每一行直至遇到第一个空白行为止
for (auto it = text.cbegin();it != text.cend() && !it->empty()++ it)cout << *it << endl;

迭代器的运算

二分查找法

auto mid = vi.begin() + vi.size()/2

五、数组

初始化

我们可以用字符串字面值对此类数组初始化。当使用这种方式时,一定要注意字符串字面值的结尾处还有一个空字符,这个空字符也会像字符串的其他字符一样被拷贝到字符数组中去:

char al[l] = {'c','+'}		// 列表初始化,没有空字符
char a2[] = {'c','+','\0'}	//列表初始化,含有显式的空字符
char a3[] = "C++"			//自动添加表示字符串结束的空字符
const char a4[6] = "Daniel";	//错误:没有空间可存放空字符!

尽管字符串字面值"Daniel"看起来只有6个字符,但是数组的大小必须至少是7,其中6个位置存放字面值的内容,另外1个存放结尾处的空字符。

不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值:

int a[] = {1,2,3};	
int a2[] = a;	//err
a2 = a;			//err

理解复杂的数组声明

int *ptrs[10];
int (*Parray)[10] = &arr;
int (&arrRef)[10] = arr;

默认情况下,类型修饰符从右向左依次绑定。对于ptrs来说,从右向左(参见2.3.3节,第52页)理解其含义比较简单:首先知道我们定义的是一个大小为10的数组,它的名字是ptrs,然后知道数组中存放的是指向int的指针。

但是对于Parray来说,从右向左理解就不太合理了。因为数组的维度是紧跟着被声明的名字的,所以就数组而言,由内向外阅读要比从右向左好多了。由内向外的顺序可帮助我们更好地理解Parray 的含义:首先是圆括号括起来的部分,*Parray 意味着Parray是个指针,接下来观察右边,可知道Parray 是个指向大小为10的数组的指针,最后观察左边,知道数组中的元素是int。这样最终的含义就明白无误了,Parray是一个指针,它指向一个 int 数组,数组中包含 10个元素。同理,(&arrRef)表示arrRef是一个引用,它引用的对象是一个大小为10的数组,数组中元素的类型是int.
*

当然,对修饰符的数量并没有特殊限制:

int*(&arry)[10]-ptrs;// arry是数组的引用,该数组含有10个指针

按照由内向外的顺序阅读上述语句,首先知道arry是一个引用,然后观察右边知道,arry引用的对象是一个大小为10的数组,最后观察左边知道,数组的元素类型是指向int的、指针。这样,arry就是一个含有10个int型指针的数组的引用。
要想理解数组声明的含义,最好的办法是从数组的名字开始按照由内向外的顺序阅读。

数组和指针

​ 数组的元素也是对象,对数组使用下标运算符得到该数组指定位置的元素。因此像其他对象一样,对数组的元素使用取地址符就能得到指向该元素的指针:

string nums[] =("one","two""three"}//数组的元素是string对象
string *p= &nums[0];				//p指向nums的第一个元素//然而,数组还有一个特性:在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针:
string *p2 = nums;//等价于p2 = &nums[0]
++p2;			//p2指向nums[2]

由上可知,在一些情况下数组的操作实际上是指针的操作,这一结论有很多隐含的意思。其中一层意思是当使用数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组(decltype可避免):

int ia[]=0,1,2,3,4,5,6,7,8,9}// ia是一个含有10个整数的数组
auto ia2(ia);					// ia2 是一个整型指针,指向ia的第一个元素
ia2 = 42;						// 错误:ia2是一个指针,不能用int 值给指针赋值

指针也是迭代器

六、函数

1.引用传递和值传递

和其他变量一样,形参的类型决定了形参和实参的交互的方式。如果形参是引用类型,他将绑定到对应的形参上;否则,将实参的值拷贝后赋给形参,形参和实参是两个独立的对象。

2.传值参数

指针形参

指针的行为和其他非引用类型一样。当执行指针拷贝操作时,拷贝的是指针的值。拷贝之后,两个指针是不同的指针。因为指针使我们可以间接地访问它所指的对象,所以通过指针可以修改它所指对象的值:

int n = 0,i=42;
int *p= &n, *q= &i;	//p指向n;q指向主
*p=42;				//n的值改变;P不变
P=q;				//p现在指向了主;但是主和n的值都不变

指针形参的行为与之类似:

//该函数接受一个指针,然后将指针所指的值置为0
void reset(int *ip)
{*ip=0;		//改变指针ip所指对象的值ip=0;		//只改变了ip的局部拷贝,实参未被改变
}

调用reset 函数之后,实参所指的对缘被置为0,但是实参本身并没有改变:

int i=42;
reset(&i);		//改变主的值而非土的地址
cout << "i" << i << endl;	//输出i=0

如何使用指针形参交换两个整数的值

#include <iostream>
using namespace std;
int swap(int *a,int *b);
int main()
{int *p,*q;int min=10;int max=20;p=&min;    q=&max;    cout<<"交换前:a= "<<min<<",b= "<<max<<endl;swap(p,q);cout<<"交换后:a= "<<min<<",b= "<<max<<endl;return 0;
}
int swap(int *a,int *b)
{int c;c=*a;*a=*b;*b=c;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R6OUs0vx-1691733924503)(C:\Users\lijiale\AppData\Roaming\Typora\typora-user-images\image-20230718110415925.png)]

p和q分别是两个数的地址,通过对地址取内容,从而得到该数的值,交换的时候也应该是将指针指向的数进行交换。但是但是如果写成下面的形式,就无法进行交换。

#include <iostream>
using namespace std;
int swap(int *a,int *b);
int main()
{int *p,*q;int min=10;int max=20;p=&min;q=&max;	cout<<"交换前:a= "<<min<<",b= "<<max<<endl;swap(p,q);cout<<"交换后:a= "<<min<<",b= "<<max<<endl;return 0;
}
int swap(int *a,int *b)
{int *c;c=a;a=b;b=c;	 
}

这是因为在swap函数体内部,只是交换了两个形参指针本身的值,未能影响实参。这时候如果在形参里面也有一条打印语句的话,能够清晰的看到在被调函数里面,确实交换了指针的值,但是这只在局部范围内有效,调用完毕回到主函数就失效了。

3.传引用参数

通过使用引用形参,允许函数改变一个或多个实参的值。

使用引用避免拷贝。当函数无须修改引用形参的值时最好使用常量引用。

bool isShorter(const string &s1,const string &s2)
{return s1.size() < s2.size();
}

使用形参隐式返回额外信息

一种方法是定义一个新的数据类型,让它包含位置和数量两个成员。还有另一种更简单的方法,我们可以给函数传入一个额外的引用实参,令其保存字符出现的次数:

//返回s中c第一次出现的位置索引
//引用形参occurs负责统计c出现的总次数
string::size _type find char(const string &s, char c,string::size _type &occurs)
{auto ret = s.size();	// 第一次出现的位置(如果有的话)occurs = 0;				//设置表示出现次数的形参的值for (decltype(ret) i = 0;!= S.size();++i) {if (s[il == c){if (ret ==  S.size())ret = i;	//记录c第一次出现的位置++occurs;		//将出现的次数加1}}
return ret;			//出现次数通过occurs 隐式地返回
}

当我们调用find_char 函数时,必须传入三个实参:作为查找范围的一个 string 对像要找的字符以及一个用于保存字符出现次数的 size_type。

4.数组形参

int a[] = {0,1,2};	//含有3个整数的数组
int a2[]=a	;		//错误:不允许使用一个数组初始化另一个数组
a2 = a;				//错误:不能把一个数组直接赋值给另一个数组

所以无法以值传递的方式使用数组参数。

但因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。

尽管不能以值传递的方式传递数组,但是我们可以把形参写成类似数组的形式:

//尽管形式不同,但这三个print 函数是等价的
//每个函数都有一个const int*类型的形参
void print(const int*);	
void print(const int []);		//可以看出来,函数的意图是作用于一个数组
void print(const int[10]);		// 这里的维度表示我们期望数组含有多少元素,实际不一定
//尽管表现形式不同,但上面的三个函数是等价的:每个函数的唯一形参都是const int*类型的。当编译器处理对 print 函数的调用时,只检查传入的参数是否是const int*类型:
int i=0,j[2] ={0,1);
print(&i);					// 正确:&i的类型是int*
print(j);					// 正确:j转换成 int*并指向j[0]

如果我们传给print 函数的是一个数组,则实参自动地转换成指向数组首元素的指针,数组的大小对函数的调用没有影响。

5.返回数组指针

因为数组不能被拷贝,所以函数不能返回数组。不过,函数可以返回数组的指针或引用(参见五、复杂)。虽然从语法上来说,要想定义一个返回数组的指针或引用的函数比较烦琐,但是有一些方法可以简化这一任务,其中最直接的方法是使用类型别名:

typedef int arrT[10];// arrT是一个类型别名,它表示的类型是含有10个整数的数组
using arrT = int[10];// arrT的等价声明
arrT* func(int i);	//func返回一个指向含有10个整数的数组的指针

其中arrT 是含有10个整数的数组的别名。因为我们无法返回数组,所以将返回类型定义成数组的指针。因此,func 函数接受一个int 实参,返回一个指向包含10个整数的数组的指针。

声明一个返回数组指针的函数

要想在声明func时不使用类型别名,我们必须牢记被定义的名字后面数组的维度:

int arr[10];// arr是一个含有10个整数的数组
int *pl[10];//p1是一个含有10个指针的数组
int (*p2)[10] = &arr;//p2是一个指针,它指向含有10个整数的数组

和这些声明一样,如果我们想定义一个返回数组指针的函数,则数组的维度必须跟在函数名字之后。然而,函数的形参列表也跟在函数名字后面且形参列表应该先于数组的维度。因此,返回数组指针的函数形式如下所示:

Type (*function (parameter _list) ) [dimension]
类似于其他数组的声明,Type 表示元素的类型,dimension 表示数组的大小。(*function(parameter _list))两端的括号必须存在,就像我们定义p2时两端必须有括号一样。如果没有这对括号,函数的返回类型将是指针的数组。
举个具体点的例子,下面这个func函数的声明没有使用类型别名:
int (*func(int i))[10];
可以按照以下的顺序来逐层理解该声明的含义:
func(int i)表示调用func函数时需要一个int类型的实参。
(*func(int i))意味着我们可以对函数调用的结果执行解引用操作。
(*func (int i))[10]表示解引用func的调用将得到一个大小是10的数组。
int (*func (int i))[10] 表示数组中的元素时int类型

改进:尾置返回类型

auto func(int i) -> int(*)[10];

6.函数重载

不允许两个函数除了返回类型外其他所有要素都相同。

七、类

一个const成员函数如果以引用的形式返回*this,,那么它的返回类型将是常量引用。

的声明,Type 表示元素的类型,dimension 表示数组的大小。(*function(parameter _list))两端的括号必须存在,就像我们定义p2时两端必须有括号一样。如果没有这对括号,函数的返回类型将是指针的数组。
举个具体点的例子,下面这个func函数的声明没有使用类型别名:
int (*func(int i))[10];
可以按照以下的顺序来逐层理解该声明的含义:
func(int i)表示调用func函数时需要一个int类型的实参。
(*func(int i))意味着我们可以对函数调用的结果执行解引用操作。
(*func (int i))[10]表示解引用func的调用将得到一个大小是10的数组。
int (*func (int i))[10] 表示数组中的元素时int类型


改进:尾置返回类型```c++
auto func(int i) -> int(*)[10];

6.函数重载

不允许两个函数除了返回类型外其他所有要素都相同。

一个const成员函数如果以引用的形式返回*this,,那么它的返回类型将是常量引用。

因为非常量版本的函数对于常量对象是不可用的,所以只能在一个常量对象上调用const成员函数。

其他

Rvalue references 右值引用

非必要的拷贝 unnecessary copying = steal 偷

右值:

//int实验
a + b = 42;//err
//string实验
string s1("Hello");
string s2("World");
s1 + s2 = s2;//pass,s1 = Hello,s2 = World
string() = "World";//pass 临时对象也是右值
//complex实验
complex<int> c1(3,8),c2(1,0);
c1 + c2 = complex<int>(4,9); //pass,c1:(3,8),c2:(1,0)
complex<int>() = complex<int>(4,9);//pass

不可对右值进行操作:
在这里插入图片描述

foo()返回的是值(int),在对右值进行取地址操作&foo(),是不允许的

用法:

对于insert操作,提供了两个函数:
1.copy
insert(...,&x)	//x是普通的值
2.move
insert(...,&&x) //x是右值(临时对象),此时取右值引用

由于vector放的是Mystring,于是class Mystring 有两个构造ctor: move是浅拷贝
在这里插入图片描述

深拷贝与浅拷贝:

在这里插入图片描述

内存管理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可变参数模板 Variadic Templates

例一、可变模板参数(递归调用)

在这里插入图片描述

max函数比大小

在这里插入图片描述

处理print函数

例二、递归继承

处理的是类型(type),使用的是class template

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TEmUDRpJ-1691734666845)(C:\Users\lijiale\AppData\Roaming\Typora\typora-user-images\image-20230713113744487.png)]

例三、递归复合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N4VzmZjn-1691734666846)(C:\Users\lijiale\AppData\Roaming\Typora\typora-user-images\image-20230713115717968.png)]

相关文章:

C++复习笔记——primer第五版

文章目录 一、引用和指针1.引用2.指针2.1利用指针访问对象2.2指针的值或指针所指对象的值的改变 3.赋值和指针4.指向指针的引用 二、String1.初始化String对象的方式2. string对象上的操作3.使用getline读取一整行4.字面值和字符串相加5.使用for循环改变字符串中的字符 三、Vec…...

ElasticSearch:项目实战(2)

ElasticSearch: 项目实战 (1) 需求&#xff1a; 新增文章审核通过后同步数据到es索引库 1、文章服务中添加消息发送方法 在service层文章新增成功后&#xff0c;将数据通过kafka消息同步发送到搜索服务 Autowiredprivate KafkaTemplate<String,String> kafkaTemplate;/…...

Eleastisearch5.2.2利用镜像迁移构建实例后ES非健康状态

正常迁移完成后启动服务&#xff0c;查看ES非健康状态 此时观察ES集群状态&#xff1a;curl -XGET -u elastic:xxx localhost:9200/_cluster/health?pretty 注意到"active_shards_percent_as_number" : 88.8888 该项的值不产生变化;集群状态"status" : “…...

sealos安装k8s

一、前言 1、我前面文章有写过使用 kubeadm 安装的方式&#xff0c;大家可以去参考 &#xff08;二&#xff09;k8s集群安装&#xff0c;有一系列的k8s文章说明 2、安装k8s的方式有很多 kubeadmsealoskubespray等等 3、关于sealos来安装 k8s &#xff0c;也是非常建议大家去…...

经典贪吃蛇游戏 - 用 C 语言实现控制台版

在本篇博客中&#xff0c;我们将一起来实现经典的贪吃蛇游戏&#xff0c;使用 C 语言编写&#xff0c;并在控制台中运行。这个小游戏会让你回忆起童年的经典游戏体验。我们将从游戏的初始化开始&#xff0c;逐步实现游戏的各个功能&#xff0c;包括蛇的移动、食物的生成、得分的…...

安灯Andon系统的应用与优势

安灯系统是一款与硬件相结合&#xff0c;实时了解机台与工位状态&#xff0c;让异常的信息得到快速、高效的解决的系统软件&#xff0c;同时记录每次异常报警的种类、响应时间和处理问题用时&#xff0c;提供改善生产管理和人员考核的数据参考&#xff0c;实现透明、快速的生产…...

2023年的C++基础笔记

C 基本语法 对象 - 对象具有状态和行为。例如&#xff1a;一只狗的状态 - 颜色、名称、品种&#xff0c;行为 - 摇动、叫唤、吃。对象是类的实例。 类 - 类可以定义为描述对象行为/状态的模板/蓝图。 方法 - 从基本上说&#xff0c;一个方法表示一种行为。一个类可以包含多个…...

综合能源系统(6)——综合能源综合评估技术

综合能源系统关键技术与典型案例  何泽家&#xff0c;李德智主编 综合能源系统是多种能源系统非线性耦合的、多时间与空间尺度耦合的“源-网-荷一储”一体化系统&#xff0c;通过能源耦合、多能互补&#xff0c;能够实现能源的高效利用&#xff0c;并提高新能源的利用水平。对…...

华为OD机试真题 Java 实现【寻找相同子串】【2023 B卷 100分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…...

软件外包开发的桌面客户端开发

跨平台桌面客户端开发工具允许开发者在多个操作系统上构建应用程序&#xff0c;从而实现一次编码、多平台运行的目标。以下是几个常见的跨平台桌面客户端开发工具以及它们的特点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&a…...

PAT(Advanced Level) Practice(with python)——1058 A+B in Hogwarts

Code A,B map(str,input().split()) g1,s1,k1 A.split(.) g2,s2,k2 B.split(.) g int(g1)int(g2) s int(s1)int(s2) k int(k1)int(k2) if k>29:s1k%29 if s>17:g1s%17 print(str(g).str(s).str(k))...

【ES】笔记-ES6的函数rest参数用法

es6中引入了rest参数&#xff0c;样式形如…xxx&#xff0c;用于获取函数的多余参数&#xff0c;这样就不需要使用arguments对象了。rest参数搭配的一个变量是一个数组&#xff0c;该变量将多余的参数放入数组中。例如&#xff1a; function add(...value){console.log(value);…...

【MOOC】北京理工大学Python网络爬虫与信息提取慕课答案-综合挑出了一些很难评的慕课测验题

1 Requests库中的get()方法最常用&#xff0c;下面哪个说法正确&#xff1f;‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬…...

【论文阅读】基于深度学习的时序预测——Crossformer

系列文章链接 论文一&#xff1a;2020 Informer&#xff1a;长时序数据预测 论文二&#xff1a;2021 Autoformer&#xff1a;长序列数据预测 论文三&#xff1a;2022 FEDformer&#xff1a;长序列数据预测 论文四&#xff1a;2022 Non-Stationary Transformers&#xff1a;非平…...

谷粒商城第十一天-完善商品分组(主要添上关联属性)

目录 一、总述 二、前端部分 2.1 改良前端获取分组列表接口及其调用 2.2 添加关联的一整套逻辑 三、后端部分 四、总结 一、总述 前端部分和之前的商品品牌添加分类差不多。 也是修改一下前端的分页获取列表的接口&#xff0c;还有就是加上关联的那一套逻辑&#xff0c;…...

C++笔记之函数参数列表中设置默认值

C笔记之函数参数列表中设置默认值 code review! 代码 #include <iostream>// 函数声明时设置默认值 void printInfo(std::string name "Unknown", int age 0);int main() {printInfo(); // 使用默认参数值printInfo("Alice", 25);…...

Verilog求log10和log2近似

Verilog求log10和log2近似 Verilog求10对数近似方法&#xff0c;整数部分用位置index代替&#xff0c;小数部分用查找表实现 参考&#xff1a; Verilog写一个对数计算模块Log2(x) FPGA实现对数log2和10*log10...

二叉树小结

二叉树 树的遍历(如何遍历&#xff0c;如何利用特性问题) 前序遍历&#xff08;中前后&#xff09; 递归 class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> res new ArrayList<>();inorder(root, res);return res…...

vue二进制下载

封装axios&#xff0c;/api/request import axios from axios import store from /store import Vue from vue import { Message, MessageBox } from element-uiimport { getToken } from /utils/authaxios.defaults.headers[Content-Type] application/json;charsetutf-8 co…...

c++QT文件操作

1 介绍 QT的文件操作来源于其抽象基类QIODevice&#xff0c;中用于处理输入输出设备。提供了统一的接口来处理不同类型的数据源&#xff0c;如文件、套接字、缓冲区等。QIODevice 主要用于读取和写入数据&#xff0c;无论数据来自何种源头&#xff0c;都可以通过 QIODevice 统一…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...