[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for

这篇具有很好参考价值的文章主要介绍了[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

 目录

1、引用 -- &

1.1 引用的概念

1.2 引用特性

1.3 常引用 -- 权限问题

1.4 引用的使用场景

1.4.1 做参数

1.4.2 做返回值

注意

1.5 传值、传引用的效率比较

1.6 引用和指针的区别

2、内联函数

2.1 概念

转存失败重新上传取消​编辑转存失败重新上传取消​编辑2.2 特性

3、auto

3.1 auto简介

3.2 auto的使用细则

3.3 auto不能推导的场景

3.4 auto与for合用


1、引用 -- &

1.1 引用的概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间

比如:李逵,在家称为“铁牛”,江湖上人称“黑旋风”。同一个人,只不过是两个名字。

语法: 类型& 引用变量名(对象名) = 引用实体;

&是引用的符号,在C语言中&也表示取地址,还表示按位与,本质是运算符重载,运算符重载,一个符号会根据不同的场景,编译器会自己确定含义。

我们举例来看看&:

int main()
{
	int a = 10;
	int& b = a;//定义引用类型
	int& c = b;

	cout << "a = " << a << ",地址:" << &a << endl;
	cout << "b = " << b << ",地址:" << &b << endl;
	cout << "c = " << c << ",地址:" << &c << endl;

	return 0;
}

运行结果: 

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

我们根据运行结果可以知道,a,b,c 指的是同一块内存空间。

注意:引用类型必须和引用实体同种类型的。

1.2 引用特性

引用有三个特性:

1. 引用在定义时必须初始化
2. 一个变量可以有多个引用;
3. 引用一旦引用一个实体,再不能引用其他实体。

其实前两条我们理解记忆就好了:

1、引用是起别名,要有对象我们才能再去起别名,不存在对象给谁起别名;

2、一个小孩,妈妈可以叫他宝贝,爸爸可以叫他贝贝,爷爷也可以叫他狗蛋是吧,所以一个对象可以有多个别名(引用)。

我们对这三个用代码写一下看看: 

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

这里32行就不是再次引用了,而是把y的值赋给ra(本质是赋给x)。

1.3 常引用 -- 权限问题

我们用代码来看:

int main()
{
	//1.权限放大
	const int x = 10;
	int& a = x;

	return 0;
}

我们来看看编译会不会出错:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

这是因为,在引用中,对原变量的引用权限不能放大。

在这段代码中,x是const修饰的常变量,只能读取,不能修改。而a是int类型,针对类型来说,它是可以修改的。因此这就是权限放大,这是错误的。

我们继续往下看:

int main()
{
    
	//2.权限平移
	const int i = 20;
	const int& j = i;

	//3.权限缩小
	int z = 30;
	const int& y = z;

	return 0;
}

我们看结果:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

对于权限的平移,权限的缩小都是没有问题的,由此我们可以看出:在引用中,对于权限来说,平移、缩小都是没有问题的,唯独要注意的是:权限不能放大。

特殊:

我们再往下看: 

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

直接能看出来,对于引用来说不能初始化为常量,这也算是权限的放大。 

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

改为const修饰就不会报错了。

最后看一个: 

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

引用的时候,不同的类型直接引用是会出错的,本质原因是int类型赋给double类型存在隐式类型转换,生成一个临时变量(具有常性),因此需要加const修饰

1.4 引用的使用场景

1.4.1 做参数

void Swap(int& left, int& right)
{
	int tmp = left;
	left = right;
	right = tmp;
}

在C语言的时候,我们交换两个数我们使用指针来交换,而C++我们就可以使用引用来交换。

我们来测试一下:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

1.4.2 做返回值

我们先来看一段代码:

int func()
{
	int n = 0;
	n++;
	return n;
}
int main()
{
	cout << func() << endl;

	return 0;
}

运行结果:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

这是是一个传值返回,我们来深究传值返回的过程:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

传值返回的时候会产生一个临时变量,跟传参一样,临时变量会先把n拷贝下来,然后再拷贝给函数调用,传值返回的类型其实是临时变量的类型,那么为什么要产生一个临时变量呢,直接返回n不香吗?

这是因为在函数调用的时候,功能函数会建立函数栈帧,而功能函数的每一条语句执行完后,函数栈帧会自动销毁,这时功能函数的整个函数体,包括函数体里的所有内容都随之销毁,返回的变量生命周期也就结束了。但是编译器在这里产生一个临时变量,要是小就用寄存器存储,将返回值拷贝给临时变量,再又临时变量拷贝给调用的函数,这就不会出错了。

有了上面的理解,我们再来看一段代码:

int& func()
{
	int n = 0;
	n++;
	return n;
}
int main()
{
	int& ret = func();
	cout << ret << endl;
	cout << ret << endl;

	return 0;
}

运行结果:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

此代码的返回值是int&,而传引用是给变量起别名,而在这里返回的是别名,调用完func函数,栈帧销毁了,但是空间还在(类似于订酒店,我退房了,但是房间还在,别人还可以使用),给n起了别名之后再去打印,还是操作的n的那块空间,那块空间可能被清理的,也有可能还没有清理,如果没清理,那块空间的值还是1,如果被清理了可能就是其他值了。

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

注意

我们看上面的代码,在第二次打印的时候,n的值明显就不正确了,出了函数作用域,func函数被销毁了,我们再去访问那块空间的时候,就是非法访问了,这就是引用的一种野指针。

因此这里要注意:如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。

1.5 传值、传引用的效率比较

我们用代码来测试一下:

#include <time.h>
struct A 
{ 
	int a[10000]; 
};
void TestFunc1(A a) {}
void TestFunc2(A& a) {}
void TestRefAndValue()
{
	A a;
	// 以值作为函数参数
	size_t begin1 = clock();
	for (size_t i = 0; i < 10000; ++i)
		TestFunc1(a);
	size_t end1 = clock();

	// 以引用作为函数参数
	size_t begin2 = clock();
	for (size_t i = 0; i < 10000; ++i)
		TestFunc2(a);
	size_t end2 = clock();

	// 分别计算两个函数运行结束后的时间
	cout << "TestFunc1 time:" << end1 - begin1 << endl;
	cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main()
{
	TestRefAndValue();
	return 0;
}

运行结果:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

#include <time.h>
struct A { int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A& TestFunc2() { return a; }
void TestReturnByRefOrValue()
{
	// 以值作为函数的返回值类型
	size_t begin1 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc1();
	size_t end1 = clock();

	// 以引用作为函数的返回值类型
	size_t begin2 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc2();
	size_t end2 = clock();

	// 计算两个函数运算完成之后的时间
	cout << "TestFunc1 time:" << end1 - begin1 << endl;
	cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main()
{
	TestReturnByRefOrValue();
	return 0;
}

运行结果:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

我们看到无论是传参还是返回,传引用的效率明显要高于传值。

原因: 以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。

1.6 引用和指针的区别

语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

int main()
{
    int a = 10;
    
    int& ra = a;
    ra = 20;
    
    int* pa = &a;
    *pa = 20;
    
    return 0;
}

我们来看引用和反汇编代码的对比:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

引用和指针的不同点:

1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用在定义时必须初始化,指针没有要求
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
4. 没有NULL引用,但有NULL指针
5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全

2、内联函数

2.1 概念

inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。

我们来看一下平常我们写的代码:

int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int ret = 0;
	ret = Add(1, 2);
	return 0;
}

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

我们可以看到,这里是在调用函数,但是我们要是不断要用Add函数的时候,不断的调用效率会比较低,因此在C++中,我们引入了内联函数(inline)。

inline int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int ret = 0;
	ret = Add(1, 2);
	return 0;
}

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

我们可以看到,加了inline变为内联函数后,就不再是调用了,直接用函数体替换了函数调用,不用开栈帧,可以提高效率。

看到这是不是想到,C++的内联函数像是C语言的宏。

C++中的内联函数确实和C语言的宏用途是一样的,对于短小且频繁调用的函数,C语言用宏来代替函数,C++中用内联函数。

C++是全面兼容C语言的,我们直接用宏就可以了,那为什么我们还要使用内联函数呢?

1、宏在写的时候容易出错,且没有类型的检查,还不能调试。

2、内联函数会对参数的类型进行检查,还可以调试,书写上就是正常的写功能函数,在返回值类型前加inline。

如果想要看底层是调用还是直接展开的,查看方式:
1. 在release模式下,查看编译器生成的汇编代码中是否存在call Add
2. 在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不会对代码进行优化,以下给出vs2019的设置方式)

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

2.2 特性

1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。
2. inline对于编译器而言只是一个建议,编译器会自动优化,如果内联函数内存在循环/递归的时候,编译器会自动优化忽略掉内联。(一般建议10行以内)

3. inline不建议声明和定义分离,分离会导致链接错误。因为inline直接再调用处被展开,(不会出现在符号表中)就没有函数地址了,链接就会找不到。

对于第二点我们做一下实验:

inline int Add(int x, int y)
{
	int sum = x + y;
	sum += x * y;
	sum += x * y;
	sum += x * y;
	sum += x * y;
	sum += x * y;
	sum += x * y;
	sum += x * y;
	sum += x * y;
	sum += x * y;
	return sum;
}
int main()
{
	int ret = 0;
	ret = Add(1, 2);
	return 0;
}

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

这里内联函数函数体一共写了十一行就算是函数调用了。

3、auto

3.1 auto简介

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量。C++11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

auto我们在C语言期间就接触过,C语言期间定义的局部变量默认是用auto修饰,因此我们在定义变量的时候从来不加auto,也就没人在意。但是到了C++11时期,auto有了新的身份,它可以自动推导类型。

我们来看一段代码,看看auto的自动推导类型:

int testAuto()
{
	return 1;
}
int main()
{
	int a = 0;
	auto b = a;
	auto c = 'c';
	auto ret = testAuto();

	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(ret).name() << endl;

	return 0;
}

运行结果: 

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

这段代码里面 typeid(变量名).name() 是推导变量类型的一个函数。

我们可以看到auto很智能,可以根据赋的值来推导类型。

注意:使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。

3.2 auto的使用细则

1. auto与指针和引用结合起来使用:用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&。

int main()
{
	int x = 10;
	auto a = &x;
	auto* b = &x;
	auto& c = x;

	cout << typeid(a).name() << endl;
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;

	return 0;
}

运行结果: 

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

2. 在同一行定义多个变量:当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

void TestAuto()
{
    auto a = 1, b = 2;
    auto c = 3, d = 4.0; // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

3.3 auto不能推导的场景

1. auto不能作为函数的参数

// 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{}

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

2. auto不能直接用来声明数组

void TestAuto()
{
    int a[] = {1,2,3};
    auto b[] = {4,5,6};
}

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

3.4 auto与for合用

按照C语言我们的写法,遍历数组是下面的代码

int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
		array[i] *= 2;
	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
		cout << array[i] << " ";
	cout << endl;

	return 0;
}

运行结果:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言


我们现在也可以使用auto这样来遍历数组:

int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (auto e : array)
		cout << e << " ";

	return 0;
}

运行结果:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

我们这里使用的是范围 for ,for循环后的括号由冒号”:“分为两个部分:第一部分是范围内用于迭代的变量,第二部分表示迭代的范围。这里会自动判断结束的。

这里的e是取到数组里的元素,然后打印,不会影响数组元素。

如果想改变数组元素,我们可以使用auto& e,这是对数组元素起别名,直接改变数组元素,auto取到元素后会自动推导类型的。如下:

int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (auto& e : array)
		e *= 2;
	for (auto e : array)
		cout << e << " ";

	return 0;
}

运行结果:

[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for,C++,数据结构,c++,算法,开发语言

我们可以看到结果,这样写就把数组元素改了。文章来源地址https://www.toymoban.com/news/detail-608643.html

到了这里,关于[C++] C++入门第二篇 -- 引用& -- 内联函数inline -- auto+for的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++初阶】C++基础(下)——引用、内联函数、auto关键字、基于范围的for循环、指针空值nullptr

      目录 1. 引用 1.1 引用概念 1.2 引用特性 1.3 常引用 1.4 使用场景 1.5 传值、传引用效率比较 1.6 引用和指针的区别 2. 内联函数 2.1 概念 2.2 特性 3.auto(C++11) 3.1 类型别名思考 3.2 auto简介 3.3 auto的使用细则 3.4 auto不能推导的场景 4. 基于范围的for循环(C++11) 4.1 

    2024年02月15日
    浏览(77)
  • 【C++初阶】二、入门知识讲解(引用、内联函数、auto关键字、基于范围的for循环、指针空值nullptr)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【C++初阶】一、入门知识讲解 (C++、命名空间、C++输入输出、缺省参数、函数重载)-

    2024年02月04日
    浏览(68)
  • 【C++入门】引用、内联函数、auto 关键字

    从语法上理解,引用就是给变量取一个 别名 ,它没有独立空间,和它引用的变量共用一块空间。 例子: 值得注意的是,C++ 中的引用一经初始化,后面是改变不了指向的(这点与Java有所不同),而且引用是必须初始化的。 引用的类型也必须和原变量对应,显然,你肯定不能

    2024年02月16日
    浏览(47)
  • 【C++】引用、内联函数、auto关键字等

    前言:在前面我们讲解了C++入门基础的一些学习例如命名空间、缺省参数、函数重载等。今天我们将进一步的学习,跟着博主的脚步再次往前迈一步吧。 💖 博主CSDN主页:卫卫卫的个人主页 💞 👉 专栏分类:高质量C++学习 👈 💯代码仓库:卫卫周大胖的学习日记💫 💪关注博

    2024年02月20日
    浏览(68)
  • 【C++初阶(三)】引用&内联函数&auto关键字

    目录  前言  1. 引用   1.1 引用的概念   1.2 引用的特性  1.3 引用的权限  1.4 引用的使用  1.5 引用与指针的区别 2. 内联函数 2.1  什么是内联函数 2.2  内联函数的特性  3. auto  3.1 auto简介  3.2 auto使用规则  3.3 auto不能使用的场景 4.  基于范围的for循环  4.1 范围for使用

    2024年02月08日
    浏览(61)
  • 【C++初阶】C++入门——内联函数、auto、范围for、nullptr

     普通的函数在调用的时候会开辟函数栈帧,会产生一定量的消耗,在C语言中可以用 宏函数 来解决这个问题,但是宏存在以下缺陷: 复杂、容易出错、可读性差、不能调试 。为此,C++中引入了 内联函数 这种方法。  以 inline 修饰 的函数叫做内联函数, 编译时 C++编译器会

    2024年02月16日
    浏览(44)
  • C++入门:内联函数,auto,范围for循环,nullptr

    目录 1.内联函数 1.1 概念 1.2 特性  1.3 内联函数与宏的区别 2.auto(C++11) 2.1 auto简介 2.2 auto的使用细则 2.3 auto不能推导的场景 3.基于范围的for循环(C++11) 3.1 范围for的语法 3.2 范围for的使用方法 4.指针空值nullptr(C++11) 4.1 C++98中的指针空值 以inline修饰的函数叫做内联函数,编

    2024年02月11日
    浏览(37)
  • 【C++技能树】原来比C方便这么多 --引用、内联函数、Auto、NULL与nullptr

      Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接       我会一直往里填充内容哒! 🌈LeetCode专栏:专栏链接       目前在刷初级算法的LeetBook 。若每日一题当中有力所能

    2023年04月25日
    浏览(38)
  • 【C++杂货铺】内联函数、auto、范围for、nullptr

     普通的函数在调用的时候会开辟函数栈帧,会产生一定量的消耗,在C语言中可以用 宏函数 来解决这个问题,但是宏存在以下缺陷: 复杂、容易出错、可读性差、不能调试 。为此,C++中引入了 内联函数 这种方法。  以 inline 修饰 的函数叫做内联函数, 编译时 C++编译器会

    2024年02月16日
    浏览(59)
  • 【C++心愿便利店】No.3---内联函数、auto、范围for、nullptr

    👧个人主页:@小沈YO. 😚小编介绍:欢迎来到我的乱七八糟小星球🌝 📋专栏:C++ 心愿便利店 🔑本章内容:内联函数、auto、范围for、nullptr 记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~ 提示:以下是本篇文章正文内容,下面案例可供参考 通过对C语言的学习,对于宏有了一定

    2024年02月11日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包