【C++初阶】第一站:C++入门基础(中)

这篇具有很好参考价值的文章主要介绍了【C++初阶】第一站:C++入门基础(中)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:
这篇文章是c++入门基础的第一站的中篇,涉及的知识点
函数重载:函数重载的原理--名字修饰
引用:概念、特性、使用场景、常引用、传值、传引用效率比较的知识点
【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

目录

5. 函数重载 (续)

C++支持函数重载的原理--名字修饰(name Mangling)

为什么C++支持函数重载,而C语言不支持函数重载呢?

6. 引用

引用概念

关于引用的应用:

引用特性

🚩引用在定义时必须初始化

🚩一个变量可以有多个引用

🚩引用一旦引用一个实体,再不能引用其他实体

使用场景

传值、传引用效率比较

值和引用的作为返回值类型的性能比较

关于顺序表的读取与修改

c语言接口

Cpp的接口设计:

常引用


5. 函数重载 (续)

C++支持函数重载的原理--名字修饰(name Mangling)

编译器是如何编译的?

Test.cpp

预处理头文件展开/宏替换/去掉注释/条件编译

Test.i

编译检查语法,生成汇编代码(指令级代码) -- 右击鼠标打开反汇编

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

Test.s

汇编将汇编代码生成二进制机器码

Test.o

链接合并链接,生成可执行程序(a.out / xxx.exe)

在整个编译的过程中涉及到的一个问题是什么呢?

        在一个项目里面写了一个stack.h(栈定义的各种接口)和stack.cpp ,这些各种接口不在Test.o内,而在stack.o内,那么怎么去这里找呢。那就涉及到名字去找地址,在链接的时候怎么用名字去找地址呢?

 C语言的特点呢 -- 直接用函数名去充当函数的名字

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

        这样的后果就是自己都区分不开来,所以C语言是不允许重名的。

那么C++是如何这块的问题呢?如何把两个同名的但参数类型顺序不一样的函数区分开来呢?

🎯 那就是函数名修饰规则解决这个问题

当函数只有声明没有定义的时候,就会出现以下的链接错误

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

        🌼当函数只有定义的时候,没有实现的时候,它就没有一堆汇编指令,没有指令就不能生成地址(就没有建立函数栈帧的过程,寄存器没有存地址)。所以在符号表里面拿这个名字去找的时候就找不到,以下是修饰以后的函数名,本质上它是用类型带入这个名字里面去了(函数修饰规则)

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

而C语言是直接用函数名去找:

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

在linux环境底下去看:

以下两张图均是函数名修饰规则

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

        Linux底下:c++区分函数不同的依据是去找函数的地址(本质也就是第一句指令的地址),找到地址之后,将其函数名修饰成特殊函数名:

<_Z4funcid> 意思是:四个字节,func(int,double)

<_Z4funcdi> 意思是:四个字节,func(double,int)

🍔在符合表里面:

        用一个独特的符号去代表一个类型,跟据类型的个数不同、类型不同、类型的顺序不同,修饰出了的名字就是不一样的,所以根据这点,就可以在函数名相同的情况下区分不同的函数。

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

vs2019底下:

void __cdecl func(int,double)" (?func@@YAXHN@Z)

void __cdecl func(double,int)" (?func@@YAXNH@Z)

因为这两个函数虽然函数名字相同,但是函数类型的顺序不同,所以编译器会根据情况修饰成特殊的函数名

问题:

函数名修饰规则带入返回值,返回值不能能否构成重载? 不能。

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

为什么C++支持函数重载,而C语言不支持函数重载呢?

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接
【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux
【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux
1.实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们
可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标
文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。那么
怎么办呢?
2. 所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就
会到b.o的符号表中找Add的地址,然后链接到一起。(老师要带同学们回顾一下)
3. 那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的
函数名修饰规则。
4. 由于Windows下vs的修饰规则过于复杂,而Linux下g++的修饰规则简单易懂,下面我们使
用了g++演示了这个修饰后的名字。
5. 通过下面我们可以看出gcc的函数修饰后名字不变。
而g++的函数修饰后变成:【_Z+函数长度+函数名+类型首字母】
  • 采用

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

结论:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。
  • 采用C语言编译器编译后结果

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参
数类型信息添加到修改后的名字中。
  • Windows下名字修饰规则

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

对比Linux会发现,windows下vs编译器对函数名字修饰规则相对复杂难懂,但道理都
是类似的,我们就不做细致的研究了。
6. 通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修
饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载

7. 如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。

6. 引用

引用概念

        引用不是新定义一个变量,而 是给已存在变量取了一个别名 ,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
💤现实生活来说:比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"

        

        C++为了在拓展语法的过程中,为了防止创新符号太多不好记忆,直接沿用C语言的符号,让其一个符号赋予了多重意思,&在这边不是取地址的意思,而是引用操作符

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

当b++时,a也会同时++,当两条语句都++时,那么这个值就变为2

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

代码实现:

int main()
{
	int a = 0;
	int& b = a;//引用

	cout << &a << endl;
	cout << &b << endl;

	return 0;

}
输出:
【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux
注意: 引用类型必须和引用 实体同种类型

关于引用的应用:

1️⃣简单的应用,值的交换:
void swap(int& x1, int& x2)
 {
     int tmp = x1;
     x1 = x2;
     x2 = tmp;
 }
 int main()
 {
     int size;

     int x = 0, y = 1;
     swap(x,y);
     printf("%d %d", x, y);
 }

执行:

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

2️⃣二叉树前序遍历的应用
int TreeSize(struct TreeNode* root)
 {
 	//写法一
 	if (root == NULL)
 		return 0;
    //写法二
 	return TreeSize(root->left)
 		+ TreeSize(root->right)
 		+ 1;
 }
 void _preorder(struct TreeNode* root, int* a, int& pi)
 {
 	if (root == NULL)
 		return;
 	//用指针的方式是为了不在不同栈帧内创建i
 	a[pi] = root->val;
    pi++;
 	_preorder(root->left, a, pi);
 	_preorder(root->right, a, pi);
 }
 int* preorderTraversal(struct TreeNode* root, int& returnSize)
 {
 	int size = TreeSize(root);
 	int* a = (int*)malloc(sizeof(int) * sizeof(int));

 	int i = 0;
 	_preorder(root,a,i);
 	return a;
 }
 int main()
 {
     int size = 0;
     preorderTraversal(nullptr, size);

 }
执行:
【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux
3️⃣关于单链表的链接
前后代码对比:
【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

引用特性

🚩引用在定义时必须初始化

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

🚩一个变量可以有多个引用

int main()
{
	int a = 0;
	int& b = a;
	int& c = a;
	int& d = b;//给别名取别名,实际上是同一块空间。

    int x = 1;
	//赋值
	b = x;

	return 0;
}

代码执行变化:

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

🚩引用一旦引用一个实体,再不能引用其他实体

int main()
{
	int a = 0;
	int& b = a;

	int x = 1;
	int&b = x;

	return 0;
}

代码执行:

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

使用场景

传引用返回和传值返回:

以下的两者返回的方式有什么区别呢?

        答:这两种情况的区别,在于传值调用在函数销毁时有寄存器,传引用调用没有寄存器保存值,因为是同一个空间,引用不同于传值和传址,既然直接传的就是这个空间本身,因此既不用创建临时拷贝,也不需要传变量地址。而是直接变量进行赋值。

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

💥先来看传值返回:

        用了一个全局的寄存器eax把返回值保存起来,待Count函数栈帧销毁后,回到主函数main,再将寄存器里面的值赋值给ret

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

💨传引用返回

        这个n的别名,出了作用域就销毁(这意味着返回的值是对已被销毁的变量的引用),还给操作系统了,在还给操作系统的时候,可能将这块空间里面的值给清理了,变成随机值了。由于Count函数的返回值是无效的(引用已被销毁),所以打印ret的值将导致未定义的行为。它可能打印1,也可能打印随机值,或者可能导致程序崩溃。

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

💢那如果对代码再修改一下呢:

        这段代码是非法的。当函数 Count() 执行完毕后,局部变量 n 将被销毁,引用 ret 将会成为悬空引用(dangling reference),它指向了已经归还给操作系统的空间,该空间里面的值可能已经被初始化为随机值。因此,将对n的引用返回给调用函数是无效的,导致未定义的行为。

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

 总结:

 传引用的第一个示例还是第二个示例中,代码都是非法的,并且会导致未定义的行为

        如果函数返回时,离开函数作用域后,其栈上空间已经还给系统,因此不能用栈上的空间作为引用类型返回。如果以引用类型返回,返回值的生命周期必须不受函数的限制(即比函数生命周期长)。

        只有当出了这个作用域,这个对象还在的情况下,才可以加引用比如便用static将变量设成静态变量,或是全局变量,函数生命周期就不会影响到引用

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

代码示例:

//传引用调用
int& Count()
{
	 int n = 0;
	 n++;
	return n;
}
int main()
{
	int& ret = Count();
	//这里打印的结果可能是1,也可能是随机值
	cout << ret << endl;
	cout << ret << endl;

	return 0;
}
//传值调用
int Count()
{
	int n = 0;
	n++;


	return n;
}
int main()
{
	int ret = Count();
	
	cout << ret << endl;
	cout << ret << endl;

	return 0;
}

当变量前面有很大一块空间被占用时,有可能不会被覆盖:

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

        写一个相加两个变量值的代码:

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

代码实现:

​#include<iostream>
#include<assert.h>
int& Add(int a,int b)
{
	int c = a + b;
	return c;
}

int main()
{
	int& ret = Add(1, 2);
	Add(3, 4);
	cout << "Add(1,2) is :" << ret << endl;
}

解析:

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

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

传值、传引用效率比较

           以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效
率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。
传引用传参(任何时候都可以用)
1、提高效率
2、输出型参数(形参的修改,影响的实参)
         【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux
#include <time.h>
#include<iostream>

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;
}

 值和引用的作为返回值类型的性能比较

 传引用返回(出了函数作用域对象还在才可以用)-- static修饰的,全局变量,堆空间等等
 1、提高效率
 2、修改返回对象

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

#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语言接口
struct SeqList
{
	int a[10];
	int size;
};

//C的接口设计 
//读取第i个位置
int SLAT(struct SeqList* ps, int i)
{
	assert(i<ps->size);//防止越界
	//...
	return ps->a[i];
}
//修改第i个位置的值
void SLModify(struct SeqList* ps, int i, int x)
{
	assert(i< ps->size);
	// ...
	ps->a[i] = x;
}

        可以看待以上代码,C语言实现读取和修改结构体成员--数组元素时,是非常繁琐的,实现功能就要编写一个功能函数,但是如果换成c++的引用,那就可以一个函数实现两个功能

Cpp的接口设计:

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

代码示例:

CPP接口设计
//读 or 修改第i个位置的值
#include<iostream>
#include<assert.h>
int& SLAT(struct SeqList& ps, int i)
{
	assert(i < ps.size);

	return(ps.a[i]);

}
int main()
{
	struct SeqList s;
	s.size = 3;

	SLAT(s, 0) = 10;
	SLAT(s, 1) = 20;
	SLAT(s, 2) = 30;
	cout << SLAT(s, 0) << endl;
	cout << SLAT(s, 1) << endl;
	cout << SLAT(s, 2) << endl;

	return 0;
}

特别注意:

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

 

常引用

在引用的过程中:
1.权限可以平移
2.权限可以缩小
3.权限不能放大!!!

int main()
{

	const int a = 0;

	//权限的放大
	int& b = a;//这个是不行的!!!

	//权限的平移
	const int& c = a;

	//权限的缩小
//形象地理解: 
	int x = 0;//齐天大圣
	const int& y = x;//戴上紧箍咒的孙悟空

	return 0;
}

赋值:

int b = a;//可以的,因为这里是赋值拷贝,b修改不影响a

类型转换:

        在c/c++里面有个规定:表达式转换的时候会产生一个临时变量,具有常性

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

以及函数返回的时候也会产生一个临时对象

【C++初阶】第一站:C++入门基础(中),C++初阶,c++,开发语言,笔记,c语言,vs2019,linux

        本章未结束,尽快更新下一章完结此篇。文章来源地址https://www.toymoban.com/news/detail-752713.html

到了这里,关于【C++初阶】第一站:C++入门基础(中)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 从基础入门到学穿C++(C++语法基础篇)【超详细】【一站式速通】

    C++是一门什么样的语言,它与C语言有着什么样的关系? C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了 OOP(object oriented programming

    2024年04月16日
    浏览(42)
  • 从基础入门到学穿C++(类和对象篇)【超详细】【一站式速通】

    C语言是一种面向过程的语言,C++和python、java一样都是一种面向对象的语言。 面向对象编程(Object-Oriented Programming,OOP)和面向过程编程(Procedural Programming)是两种不同的编程范式 面向对象编程 :强调的是将现实世界中的事物抽象成对象,并通过对象之间的交互来实现程序

    2024年04月09日
    浏览(39)
  • C语言初阶——手把手教零基础/新手入门(万字心得笔记)

    目录 前言 一、C语言是什么? 二、开发环境 1.编译器 三、初始C语言 1.第一个C语言程序 2.数据类型 2.1 数据类型的长度 3. 变量 常量 3.1 如何定义变量 3.2 变量的分类  3.3 变量的作用域和生命周期 3.4常量 1.字面常量 2.const修饰的常变量  3.#define定义的标识符常量 4.枚举常量

    2024年02月03日
    浏览(91)
  • C++入门教程,C++基础教程(第一部分:从C到C++)七

    由C语言发展而来的一种面向对象的编程语言。 本章讲述 C++ 语言的简史,以及 C++ 语言中与面向对象关系不大、C语言中没有的特性。这些特性能够增加编程的便利性,提高程序的可扩充性。 inline 可以只在函数定义处添加,也可以只在函数声明处添加,也可以同时添加

    2024年02月02日
    浏览(44)
  • HarmonyOS第一课ArkTS开发语言(TypeScript快速入门)

    ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript(简称TS)的基础上,匹配ArkUI框架,扩展了声明式UI、状态管理等相应的能力,让开发者以更简洁、更自然的方式开发跨端应用。要了解什么是ArkTS,我们首先要了解下ArkTS、TypeScript和JavaScript之间的关系: JavaScript是一种属

    2024年02月05日
    浏览(44)
  • golang开发工程师-第一步:golang入门基础教学

    人生格言:好记性不如烂笔头! 建议:看这篇文章,前提是必须会java,javascript等一门语言。你可以把golang语言看做是缝合怪;集c,java,javascript等语言优点于一身。如果你没有任何编程语言傍身,本人还是建议你去哔站看视频,就不要在这里浪费时间了~~~ 优势一:golang代码

    2024年02月04日
    浏览(41)
  • 红袖添香,绝代妖娆,Ruby语言基础入门教程之Ruby3基础语法,第一次亲密接触EP01

    书接上回,前一篇我们在全平台构建好了Ruby3的开发环境,现在,可以和Ruby3第一次亲密接触了。 Ruby是一门在面向对象层面无所不用其极的解释型编程语言。 我们可以把编写Ruby代码看作是一场行为上的艺术,编码就像跳舞一样,Ruby的每一步都很优雅,几乎没有一步是多余的

    2024年01月20日
    浏览(55)
  • 从C语言到C++(第一章_C++入门_下篇)内联函数+auto关键字(C++11)+范围for +nullptr

    目录 1. 内联函数 1.1 内联函数的概念 1.2 内联函数的特性 1.3 宏的优缺点和替代方法 2. auto(C++11) 2.1 改版前的auto 2.2 C++11的auto 2.3 auto 的使用场景 2.4 使用auto的注意事项 3. 范围 for(C++11) 3.1 范围 for 的用法 3.2 范围 for 的使用条件 4. 指针空值 nullptr 4.1 C++ 98 中的指针空

    2023年04月21日
    浏览(45)
  • C++初阶:C++入门

    目录 一.iostream文件 二.命名空间 2.1.命名空间的定义 2.2.命名空间的使用 三.C++的输入输出 四.缺省参数 4.1.缺省参数概念 4.2.缺省参数分类 4.3.缺省参数注意事项 4.4.缺省参数用途 五.函数重载 5.1.重载函数概念 5.2.C++支持函数重载的原理--名字修饰(name Mangling) 5.3.extern \\\"C\\\" 六.引用

    2024年02月09日
    浏览(42)
  • “C++基础入门指南:了解语言特性和基本语法”

    C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式 等。熟悉C语言之后,对C++学习有一定的帮助 工作之后,看谁的技术牛不牛逼,不用看谁写出多牛逼的代码,就代码风格扫一眼,立刻就能看出来是正规军还是野生的程序员。代码的风

    2024年02月16日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包