[C++核心编程-02]----C++引用详解和使用方法分析

前言

        在C++中,引用是一个别名,它允许将一个已存在的变量或对象用不同的名称来访问。引用在定义时必须初始化,并且一旦初始化就不能再绑定其他对象,因此引用在声明时被初始化后就不能再改变引用对象。引用使用&符号进行声明。

        引用的定义形式如下:

Type& ref = variable;

        其中,Type是引用所引用对象的类型,ref是引用的名称,variable是引用所绑定的变量或对象。 

正文

01-引用简介

        C++中的引用是一个别名,可以用来访问已存在的变量或对象,相当于给变量起一个别名。引用在定义时必须初始化,且初始化后不可再绑定其他对象,即引用在声明时被初始化后就不能再改变引用对象。引用使用&符号进行声明。

        引用主要有以下特点和使用方法:

        a、别名: 引用本质上是对一个已存在对象的别名,可以通过引用来操作原始对象,实现对原始对象的直接改变。 

        b、必须初始化: 定义引用时必须进行初始化,且一旦初始化就不能再绑定其他对象。

        c、传递和修改函数参数: 可以通过引用将变量传递给函数,函数可以修改引用指向的变量,实现“引用参数”的功能,避免传递大量数据的复制。

        d、返回引用: 函数可以返回引用类型,从而可以通过函数返回值改变对象的值。

        e、方便修改对象值: 通过引用可以直接修改对象的值而无需通过指针间接修改。

        f、常引用: 通过const修饰的引用称为常引用,只能读取对象值,不能修改。

        g、注意事项: 使用引用时需要注意避免悬空引用、引用指向临时变量等问题。

02-引用的基本语法

        引用在C++中的创建需要遵循以下基本语法规则:

        a、定义引用变量:引用是通过在声明时在变量名前加上&符号来创建的,表示这是一个引用变量。

        b、初始化引用:在定义引用时必须进行初始化,即需要将引用绑定到一个已存在的变量或对象上。一旦引用被初始化后,就不能再绑定其他对象。

        c、使用引用:通过引用可以直接操作原始对象,修改引用也会影响原始对象的值。可以像使用普通变量一样使用引用。

        下面给出一个示例代码,展示引用的创建过程:在这个示例中,首先定义了一个整型变量x,然后创建了一个整型引用ref,引用了变量x。通过引用ref修改了原始变量x的值,并输出了修改前后的结果,演示了引用的创建和使用过程。

#include <iostream>
using namespace std;

int main() {
    int x = 5;  // 定义一个整型变量x,并赋初值为5
    int& ref = x;  // 创建一个整型引用ref,引用变量x

    cout << "原始变量x的值为:" << x << endl;  // 输出原始变量x的值
    cout << "引用所绑定的对象的值为:" << ref << endl;  // 输出引用所绑定对象的值

    ref = 10;  // 通过引用修改原始变量x的值

    cout << "修改后,原始变量x的值为:" << x << endl;  // 输出修改后的原始变量x的值

    system("pause");
    return 0;
}

        下面给出具体代码,用于分析引用基本语法使用过程:在这个示例中,引用b和变量a共享相同的内存空间,因此当通过引用b修改值时,也会影响到原始变量a的值。这展示了引用的一个重要特性:通过引用可以直接对原始变量进行操作,而不需要操作副本。引用在C++中的这种功能可以简化对变量的处理,提高代码的可读性和效率。这个示例通过引用实现了对原始变量的修改和输出,展示了引用的使用方式。

#include<iostream>
using namespace std;

int main()
{
	// 引用的基本语法  相同数据类型  &别名 = 原名

	int a = 10;

	// 创建引用
	int &b = a;

	b = 100;  //因为a和b是同时操作的同一个内存,因此,当改变b时,a也会改变

	cout << "a = " << a << endl;
	cout << "b = "<<b << endl;

	system("pause");
	return 0;

}

        示例运行结果如下图所示:

03-引用的注意事项

        引用在C++中是一个非常有用的特性,但同时也需要注意以下几个重要的事项:

        a、引用必须在定义时初始化:引用必须在定义的同时进行初始化,即在创建引用时必须将其绑定到某个变量上。例如int &b = a;,这里的b就是引用,它必须在定义时就绑定到变量a上。

        b、引用与原变量共享内存空间:引用本质上是原变量的别名,它们共享同一块内存空间。因此,对引用的操作会直接影响原变量的值,反之亦然。这种共享内存空间的特性是引用的重要特点。

        c、引用不能重新绑定:一旦引用绑定到某个变量上,就不能再重新绑定到其他变量。引用的绑定是一种一次性的操作,不能修改。

        d、避免悬空引用:悬空引用是指引用的目标对象已经被销毁,但引用仍然存在。如果在这种情况下使用引用,会导致未定义行为。因此,使用引用时要确保目标对象的生命周期覆盖了引用的使用范围。

        e、使用引用要小心指针:引用与指针类似,但也有不同之处。引用是一个别名,可以简化代码和提高可读性,但指针可以在运行时进行重新赋值和指向不同的对象。因此,需要根据实际情况选择使用引用还是指针。

        注:引用必须初始化。引用在初始化后,不可以进行更改。

#include <iostream>
using namespace std;

int main() {
    int a = 10;
    int &b = a; // 初始化引用b绑定到变量a
    int c = 20;

    b = c; // 修改a的值为20,因为b是a的引用

    cout << "a = " << a << endl; // 输出20
    cout << "b = " << b << endl; // 输出20

    // 尝试重新绑定引用
    int d = 30;
    // int &ref = d; // 这样会报错,引用不能重新绑定

    return 0;
}

        下面给出具体代码,用于分析引用的注意事项过程,这个示例代码主要演示了引用的两个注意事项:

        a、引用必须在定义时初始化:在代码中,定义了一个int a = 10;的变量a,并尝试定义一个引用int &b;但这句代码是错误的,因为引用在定义时必须初始化。正确的做法是int &b = a;,将引用b初始化绑定到变量a上。

        b、引用在初始化后不可以进行更改:在代码中,虽然进行了b = c;的赋值操作,但这并不是将b改成c的引用,而是将a的值修改为了c的值。由于引用本质上是指向了a的地址,所以a和b指向的地址是一样的。而c则有不同的地址。虽然地址不同,但是对应的内存单元中存储的数值可以相同。

#include<iostream>
using namespace std;

int main()
{

	int a = 10;
	// 1、引用必须初始化

//	int &b;  // 这句代码错误,必须初始化
	int  &b = a;

	// 2、引用在初始化后,不可以进行更改
	int c = 20;
	b = c;  // 这里并没有将b改成c的引用,只是一个赋值的操作,此时b指向的还是a的地址
	
	// 地址不会改变,因此可以看出,a和b的地址还是相同的,但是c和他们的地址不同,
	// 然而,虽然不同地址,但是对应的内存单元中存储的数值是可以相同的
	cout << "c = " << &c << endl;  // 0113F95C
	cout << "a = " << &a << endl;  // 0113F974
	cout << "b = " << &b << endl;  // 0113F974

	cout << "c = " << c << endl;  
	cout << "a = " << a << endl;  
	cout << "b = " << b << endl;  


	system("pause");
	return 0;

}

        示例运行结果如下图所示:

04-引用做函数参数

        当引用作为函数参数时,可以实现对参数的直接操作,而不是对参数值的拷贝。这可以减少内存消耗和提高程序的执行效率。引用作为函数参数的主要优点包括:

        a、避免参数拷贝开销:当传递非引用参数时,系统会自动进行值的拷贝,而将引用作为参数传递可以避免这种开销,提高程序效率。

        b、直接修改参数值:引用作为函数参数时,函数内对引用的操作会直接影响原始实参的值,这对函数的修改操作非常有用。

        c、返回多个值:引用可以作为返回多个值的方式,通过引用传递多个参数,并在函数内部修改这些参数的值。

        下面给出具体代码示例,演示引用作为函数参数的用法以及以上优点:在这个示例中,test1函数使用引用作为参数,实现了对传入参数的直接修改;test2函数演示了引用作为参数返回多个值的用法。

#include <iostream>
using namespace std;

// 传递引用作为参数,实现直接修改传入参数的值
void test1(int &n) {
    n++;
}

// 返回多个值,通过引用参数传递
void test2(int a, int b, int &sum, int &diff) {
    sum = a + b;
    diff = a - b;
}

int main() {
    int num = 10;
    int sum, diff;

    // 通过引用参数直接修改num的值
    test1(num);
    cout << "num after increment: " << num << endl; // 输出11

    // 返回多个值,通过引用参数传递
    test2(5, 3, sum, diff);
    cout << "sum: " << sum << ", diff: " << diff << endl; // 输出sum: 8, diff: 2

    return 0;
}

          下面给出代码,用于分析值传递、地址传递和引用传递三种方法的过程:这个示例演示了C++中的三种参数传递方式:值传递、地址传递和引用传递,并进行了交换函数的实现和调用。

        a、值传递:在mySwap01函数中,两个参数a和b被传递进去,但是在函数内部交换它们的值,并不会影响到实参。因此,ab的值不会发生改变。

        b、地址传递:在mySwap02函数中,使用指针作为参数,在函数内部通过地址修改实参的值。因此,通过传递变量地址,函数可以直接修改实参的值。在输出中,可以看到cd的值已经被交换。

        c、引用传递:在mySwap03函数中,引用被用作参数,实现了对实参的直接修改,而不是传递变量的拷贝。因此,引用传递和地址传递类似,都可以实现对实参的值的修改。在输出中,可以看到fe的值也已经被交换了。

        这个示例通过不同的参数传递方式演示了值传递、地址传递和引用传递的区别。值传递只是传递变量的副本,不会修改实参;地址传递通过传递指针可以修改实参的值;引用传递则直接修改实参的值,效果类似于地址传递。

#include<iostream>
using namespace std;


// 交换函数

// 1、值传递
void mySwap01(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
}
// 2、地址传递
void mySwap02(int *c, int *d)
{
	int temp = *c;   // 这里定义temp,不能定义指针,因为*c就已经是一个值,只需要将值赋给temp存储一下就行了
	*c = *d;
	*d = temp;
	cout << "c的地址" << c << endl;
	cout << "temp的地址" << &temp << endl;
}
// 3、引用传递
void mySwap03(int &f, int &e)  //这里参数列表中使用过了引用的方式传递参数,加&符号即可
{
	int temp = f;
	f = e;
	e = temp;
}

int main()
{

	int a = 10;
	int b = 20;
	mySwap01(a, b);  //值传递,形参不会修饰实参,也就是实参并不会改变
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	int c = 10;
	int d = 20;
	mySwap02(&c, &d);  //地址传递,形参修饰实参,也就是实参会改变
	cout << "c = " << c << endl;
	cout << "d = " << d << endl;

	int f = 10;
	int e = 20;
	mySwap03(f,e);  //引用传递,形参修饰实参,也就是实参会改变
	cout << "f = " << f << endl;
	cout << "e = " << e << endl;

	system("pause");
	return 0;

}

示例运行结果如下图所示:

05-引用做函数返回值

        当引用作为函数的返回值时,可以实现返回一个指向已存在变量或对象的引用,而不是复制一个新的变量。这样可以避免额外的内存开销,同时直接修改原始变量。引用作为函数返回值的主要优点包括:

        a、避免对象的拷贝:通过引用返回一个已存在的对象,避免了对对象进行复制构造,节省了内存空间和时间消耗。

        b、直接修改原始对象:返回引用可以直接修改原始对象的值或状态,而不是返回一个副本,使得函数能够对原始对象进行修改。

        c、返回多个值:引用可以作为一种返回多个值的方式,通过返回引用来返回多个对象或变量。

        下面给出代码示例,分析引用作为函数返回值的用法及以上优点:在这个示例中,getMax函数返回两个整数中较大的那个的引用,可以直接修改原始对象的值。在main函数中,通过调用getMax(a, b) = 100;实现了对ab值的直接修改,而不用再通过复杂的返回值或指针操作。

#include <iostream>
using namespace std;

// 返回引用,直接修改原始对象
int &getMax(int &num1, int &num2) {
    if(num1 > num2) {
        return num1;
    } else {
        return num2;
    }
}

int main() {
    int a = 10, b = 20;

    cout << "Initial values: a = " << a << ", b = " << b << endl;

    getMax(a, b) = 100;  // 直接修改a或b的值

    cout << "After modifying value: a = " << a << ", b = " << b << endl;

    return 0;
}

        接着给出具体代码,分析引用作为函数返回值的使用过程:

        注:不要返回局部变量的引用,因为局部变量存放在栈区。引用函数的调用可以作为左值。

        在这个示例中,展示了引用作为函数返回值的用法及需要注意的一些问题:

        a、不要返回局部变量的引用:在test01函数中,返回了一个指向动态分配的整型变量的引用。这里引发了一个潜在的问题,因为返回的指针对应的动态内存分配在堆区,但在函数结束后指针a被销毁,可能导致返回的引用指向的内存不再有效。

        b、引用函数的调用可以作为左值:在test02函数中,返回静态整型变量的引用。因为静态变量存放在全局区,可以保证其在程序整个生命周期中有效。因此,可以将引用函数调用作为左值,直接对函数返回的变量进行操作。

        在main函数中,分别调用test01test02函数返回引用,并将其赋值给引用变量refref2,然后输出它们的值。可以观察到,ref输出了正确的值,但第二次输出乱码,因为返回的引用指向的动态内存已经被释放。而ref2输出了静态变量的值,可以持续输出。最后通过test02() = 1000;方式实现对静态变量的直接修改,进而改变ref2的值。

        需要注意:使用引用作为函数返回值时,避免返回指向局部变量的引用,以防止悬空引用;可以返回静态变量或静态全局变量的引用,以保证返回值的有效性。

#include<iostream>
using namespace std;

//引用做函数的返回值

// 1、不要返回局部变量的引用,因为局部变量存放在栈区
int& test01()   //这里就是使用的引用返回
{
	int *a = new int(10);
	return *a;
}
// 2、引用函数的调用可以作为左值
int& test02()   //这里就是使用的引用返回
{
	static int a = 10;  // 变成了静态变量,在全局区,可以一直输出
	return a;
}

int main()
{
	// 调用引用返回函数
	int &ref = test01();  // 这里test01()以引用的方式返回的a,相当于a此时有一个别名,然后又定义了ref这个别名等于a,再进行输出
	cout << "ref = " << ref << endl;   // 这里就像是让局部变量做返回值,和栈区那一节很像,第一个正常输出,第二个乱码
	cout << "ref = " << ref << endl;

	int &ref2 = test02();
	cout << "ref2 = " << ref2 << endl;
	cout << "ref2 = " << ref2 << endl;

	test02() = 1000;  // 这里之后,ref2变成了1000,这里相当于做了一个a = 1000的操作,ref2是a的别名,因此也会改变

	cout << "ref2 = " << ref2 << endl;
	cout << "ref2 = " << ref2 << endl;
	

	system("pause");
	return 0;

}

        示例运行结果如下图所示:

06-引用的本质

        引用是C++中一个重要的特性,它实际上是一个别名,允许程序员使用一个变量的多个名称来访问相同的内存位置。引用的本质可以通过以下几点来解释:

        a、别名:引用本质上是变量的别名,即一个变量可以有多个名字来引用同一块内存位置。这使得程序员可以通过引用来操作同一个变量,而不是复制其值。

        b、地址操作:在底层实现上,引用是通过指针实现的。编译器在引用声明时会隐式地创建一个指针,并在使用引用时自动解引用。因此,引用的本质是通过指针实现的。

        c、提高代码可读性:引用的主要作用是提高代码的可读性和易用性。使用引用可以简化代码并减少冗余,使得代码更加清晰和易于理解。

        下面是一个代码示例,分析引用的本质和用法:在这个示例中,变量ref是变量x的引用,即refx的别名。通过不同的方式修改refx的值,可以观察到它们实际上指向同一个内存位置,因此修改任何一个变量的值都会影响另一个。

#include <iostream>
using namespace std;

int main() {
    int x = 10;
    int &ref = x;  // 引用变量ref是变量x的别名

    cout << "x = " << x << endl;  // 输出变量x的值
    cout << "ref = " << ref << endl;  // 输出引用ref的值

    x = 20;  // 修改变量x的值
    cout << "x = " << x << endl;  // 再次输出变量x的值
    cout << "ref = " << ref << endl;  // 输出引用ref的值,与变量x相同

    ref = 30;  // 通过引用修改变量x的值
    cout << "x = " << x << endl;  // 再次输出变量x的值,被修改为30
    cout << "ref = " << ref << endl;  // 输出引用ref的值,与变量x相同

    return 0;
}

        接着给出具体代码,分析引用的本质的使用过程:

        在这个示例中,展示了引用的本质是指针常量的概念。具体来说,对于引用int& ref1 = a;,实际上会被编译器转换为int* const ref = &a;,即ref是一个指针常量,指向不可变,但指向的值可以改变。

        在main函数中,定义了一个整型变量a并创建了一个引用ref1来引用这个变量。通过ref1 = 20;这一操作,实际上是在内部被转换为*ref = 20;,即通过引用修改了变量a的值。因此,在输出aref1的值时,它们都变成了20。

        在函数func中,参数ref1是一个引用,实际上是指针常量的概念。在函数内部对ref1的修改实际上是对其指向的变量进行修改,因此通过func(a);这一调用修改了变量a的值为100。

#include<iostream>
using namespace std;

//发现是引用,转换为 int* const ref = &a;
void func(int& ref1) {
	ref1 = 100; // ref是引用,转换为*ref = 100
}
int main() 
{
	/* 只需要记住引用是一个指针常量即可  int *const ref = &a
	*/

	// 引用相当于一个指针常量,对于指针常量来说,指向不可以更改,指向的值可以改变,因此引用不可更改
	int a = 10;
	//自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改
	
	int& ref1 = a;
	
	ref1 = 20; //内部发现ref是引用,自动帮我们转换为: *ref = 20;,一切都是在内部完成的
	
	cout << "a:" << a << endl;
	cout << "ref:" << ref1 << endl;
	
	func(a);
	
	system("pause");
	return 0;
}

        示例运行结果如下图所示:

07-常量引用

        常量引用是在引用声明中加上const修饰符的引用类型。常量引用用于限制对被引用对象的修改,即通过常量引用无法修改被引用对象的值,起到了类似于只读的作用。常量引用的本质是将被引用对象视为常量,从而在编译时就可以进行静态类型检查,以确保不会意外修改引用对象的值。

        下面是一个具体的代码示例,演示了常量引用的概念及用法:

        在这个示例中,首先定义了一个整型变量num,然后使用常量引用const int& constRef = num;来引用这个变量。常量引用限制了对num的修改,因此尝试修改constRef的值会导致编译错误。接着在main函数中输出常量引用指向变量的值,并调用函数modifyValue并传递常量引用,观察在函数内部的输出。

        函数modifyValue中的参数ref是一个常量引用,因此无法在函数内部修改其引用对象的值,只能通过该引用进行读取操作。这可以有效保护被引用对象不被意外修改,增强了程序的稳定性和安全性。

#include <iostream>
using namespace std;

void modifyValue(const int& ref) {
    // ref = 10;  // 错误:常量引用无法修改引用对象的值
    cout << "Value inside function: " << ref << endl;
}

int main() {
    int num = 5;
    const int& constRef = num;  // 常量引用,限制了对num的修改

    cout << "Value before modification: " << constRef << endl;
    // constRef = 10;  // 错误:常量引用无法修改引用对象的值
    modifyValue(constRef);  // 传递常量引用给函数

    return 0;
}

         接着给出具体代码,分析常量引用的使用过程:

        这个示例展示了常量引用的用法和作用。在函数showValue中,参数val被声明为常量引用const int& val,这意味着在函数内部无法修改val所引用的值,即无法对实参a进行修改。通过使用常量引用,可以确保在函数内部只能对被引用对象进行读取操作,而不会意外修改实参的值。

        在main函数中,定义了一个整型变量a并调用函数showValue将其传递给常量引用参数val。在函数内部打印出了val所引用的值,但无法对其进行修改。因此在最后输出a的值时,依然是初始值100,没有被修改。

#include<iostream>
using namespace std;

//打印数据函数
void showValue(const int& val) 
{
//   val  = 1000;   // 这里函数只是想要实现一个打印的操作,因此在参数列表中加入一个const来修饰,
	// 此时val便不可以进行修改,因为这是使用引用方式传递值,因此如果不加const,操作者在该函数中,
	// 进行了val重新赋值操作的话,实参a也会被改变,这就是为什么有些函数参数列表中带有const的原因
	cout << "val = " << val << endl;
}

int main()
{

	int a = 100;
	showValue(a);
	cout << "a = " << a << endl;
	
	system("pause");
	return 0;
}

        示例运行结果如下图所示:

总结

        经过上述分析,总结如下:

        引用是C++中一种重要的编程工具,可以简化代码、提高效率,并且有助于实现一些高级的编程技术。在使用引用时需要注意避免悬空引用、引用指向临时变量等问题,以确保程序的正确性和健壮性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Game Theory In Competitive Programming|Part1 (原创)

Game Theory In Competitive Programming|Part1 在算法竞赛中&#xff0c;博弈论是一个经常出现的题目类型。通常是两个人在给定规则下&#xff0c;每个人都按照最优策略进行博弈&#xff0c;我们的任务是找出获胜者。这通常是贪心算法、动态规划等算法的混合。下面&#xff0c…

Apache和Nginx的区别以及如何选择

近来遇到一些客户需要lnmp环境的虚拟主机&#xff0c;但是Hostease这边的虚拟主机都是基于Apache的&#xff0c;尽管二者是不同的服务器软件&#xff0c;但是大多数情况下&#xff0c;通过适当的配置和调整两者程序也是可以兼容的。 目前市面上有许多Web服务器软件&#xff0c;…

哈希表实现-哈希桶法

哈希桶方法 由于直接定值法实现哈希表有着明显的弊端——如果多个节点的hash值相同会往后堆积&#xff0c;所以衍生出哈希桶方法 我们的哈希表设置成一个结点指针数组&#xff0c;每个哈希值对应的是一串链表&#xff0c;形状就像一个一个的桶我们就会把hash值相同的节点放到一…

宝塔怎么配置nginx

宝塔怎么配置nginx 1.找到nginx配置位置 2.修改nginx.conf文件 3.重启nginx

21岁的人生赚51W!拒绝捞男捞女,翻身也要爱惜身体!——早读(逆天打工人爬取热门微信文章解读)

身体是革命的本钱 引言Python 代码第一篇 卢克文工作室 捞女在今天的中国是怎样的存在第二篇 人民日报 来啦 新闻早班车要闻社会政策 结尾 我将我的健康视为生活的基石 不会为了短暂的成功而牺牲 我珍惜身体 知道健康是实现梦想的前提 引言 这里毕竟是一个程序员的代码学习平台…

基于SpringBoot实现各省距离Excel导出实战

目录 前言 一、列表及图表信息展示 1、数据过滤调整 2、信息列表及图表展示 3、Excel写入 二、界面可视化 1、Echarts图表和列表展示 2、城市详情和下载功能设计 三、成果展示 1、图表展示 2、部分城市数据分析 总结 前言 今天是五一黄金周假期第二天&#xff0c;不知…

Redis(Jedis和SpringBoot整合Redis)

文章目录 1.Jedis1.介绍2.环境配置1.创建maven项目2.pom.xml引入依赖3.新建一个包并创建一个文件 3.Jedis远程连接到Redis1.Redis放到服务器可以连接的前提条件2.为Redis设置密码1.编辑配置文件2.找到 requirepass3.设置密码为root4.重启Redis&#xff0c;在shutdown的时候报错…

R语言实战——中国职工平均工资的变化分析——相关与回归分析

链接: R语言学习—1—将数据框中某一列数据改成行名 R语言学习—2—安德鲁斯曲线分析时间序列数据 R语言学习—3—基本操作 R语言学习—4—数据矩阵及R表示 R语言的学习—5—多元数据直观表示 R语言学习—6—多元相关与回归分析 1、源数据 各行业平均工资变化 各地区平均工资…

常用算法介绍

1. 冒泡排序&#xff1a;冒泡排序是一种简单的排序算法&#xff0c;它的基本思想是比较相邻的两个元素&#xff0c;如果顺序错误就交换它们的位置&#xff0c;直到所有元素都按照升序排列。 2. 快速排序&#xff1a;快速排序是一种高效的排序算法&#xff0c;它的基本思想是选取…

内网端口转发与代理

思路&#xff1a;渗透的前提是双方能够建立通信。目前无法和win7建立通信&#xff0c;但是拿到了windows2003的权限&#xff0c;所以可以在Windows2003主机上面建立节点&#xff0c;作为跳板机去访问到内网。 目前状态&#xff1a;控制win2003&#xff08;IP&#xff1a;192.1…

基于JSP的人才公寓管理系统

目录 背景 技术简介 系统简介 界面预览 背景 随着互联网的广泛推广和应用&#xff0c;人才公寓管理系统在网络技术的推动下迅速进步。该系统的设计初衷是满足住户的实际需求&#xff0c;通过深入了解住户的期望&#xff0c;开发出高度定制化的人才公寓管理系统。利用互联网…

如何进行Go语言的性能测试和调优?

文章目录 开篇一、性能测试1. 使用标准库中的testing包2. 使用第三方工具 二、性能调优1. 优化算法和数据结构2. 减少不必要的内存分配和垃圾回收3. 并发和并行 结尾 开篇 Go语言以其出色的性能和简洁的语法受到了广大开发者的喜爱。然而&#xff0c;在实际开发中&#xff0c;…

39.乐理基础-拍号-认识音符

拍号是一个分数的形式&#xff0c;如下图篮色的圈圈里的东西&#xff0c;但它的实际意义和分数没什么关系&#xff0c;只是外观上是一个分数的形式 单独拿出拍号&#xff0c;如下图&#xff1a; 然后接下来只要搞懂什么是 Y分音符、一拍、小节就可以了。 音符&#xff1a; 控…

Java | Leetcode Java题解之第67题二进制求和

题目&#xff1a; 题解&#xff1a; class Solution {public String addBinary(String a, String b) {StringBuffer ans new StringBuffer();int n Math.max(a.length(), b.length()), carry 0;for (int i 0; i < n; i) {carry i < a.length() ? (a.charAt(a.leng…

特征提取(Feature Extraction)常见统计特征笔记(三)

统计特征是描述数据集中值的一组量&#xff0c;通常用于了解数据的分布、集中趋势和变异程度。常见的统计特征包括均值、中位数、众数、标准差、方差等。下面会详细解释每个统计特征&#xff0c;并给出相应的Python代码。 1、均值&#xff08;Mean&#xff09;&#xff1a;所有…

分布式存储 Ceph 的演进经验

从 2004 年到今天&#xff0c;Ceph 的存储后端一直都在演变&#xff0c;从最开始基于 B 树的 EBOFS 演变到今天的 BlueStore&#xff0c;存储后端已经变得非常成熟&#xff0c;新的存储系统不仅能够提供良好的性能&#xff0c;还有着优异的兼容性。我们在这篇文章中将要简单介绍…

华为eNSP小型园区网络配置(上)

→跟着大佬学习的b站直通车← 目标1&#xff1a;dhcp分配ip地址 目标2&#xff1a;内网用户访问www.yzy.com sw1 # vlan batch 10 # interface Ethernet0/0/1port link-type accessport default vlan 10 # interface Ethernet0/0/2port link-type trunkport trunk allow-pass…

【Linux】网络连接配置——nmcli工具配置连接增删改查实例

nmcli工具配置连接增删改查实例 &#xff08;一&#xff09;网络连接配置基本项目1.网络接口配置2.主机名配置3.DNS服务器配置 &#xff08;二&#xff09;网络连接配置文件&#xff08;三&#xff09;网络配置方法&#xff08;四&#xff09;nmcli工具配置连接管理1.增2.查3.改…

prometheus+grafana的安装与部署及优点

一、Prometheus 的优点 1、非常少的外部依赖&#xff0c;安装使用超简单&#xff1b; 2、已经有非常多的系统集成 例如&#xff1a;docker HAProxy Nginx JMX等等&#xff1b; 3、服务自动化发现&#xff1b; 4、直接集成到代码&#xff1b; 5、设计思想是按照分布式、微服…

GPT-3

论文&#xff1a;Language Models are Few-Shot Learners&#xff08;巨无霸OpenAI GPT3 2020&#xff09; 摘要 最近的工作表明&#xff0c;通过对大量文本进行预训练&#xff0c;然后对特定任务进行微调&#xff0c;在许多NLP任务和基准方面取得了实质性进展。虽然这种方法…