【巧学C++之西游篇】No.2 --- C++闹天宫,带着“重载“和“引用“

news2024/12/24 17:02:12

文章目录

  • 前言
  • 🌟一、函数重载
    • 🌏1.1.函数重载概念
    • 🌏1.2.C++支持函数重载的原理 -- 名字修饰
  • 🌟二、引用
    • 🌏2.1.引用的概念
    • 🌏2.2.引用特性
    • 🌏2.3.常引用
    • 🌏2.4.使用场景
    • 🌏2.5.传值、传引用效率比较
    • 🌏2.6.引用和指针的区别
  • 🌟三、末尾彩蛋(带你回溯时空联想之前)


前言

在这里插入图片描述

👧个人主页:@小沈熬夜秃头中୧⍤⃝❅
😚小编介绍:欢迎来到我的乱七八糟小星球🌝
📋专栏:C++
🔑本章内容:C++入门(二)
记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~


提示:以下是本篇文章正文内容,下面案例可供参考

🌟一、函数重载

函数重载

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。
比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!"

🌏1.1.函数重载概念

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题

1. 参数类型不同
#include<iostream>
using namespace std;
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}
double Add(double left, double right)
{
	cout << "double Add(double left, double right)" << endl;
	return left + right;
}
int main()
{
	cout << Add(1, 2) << endl;
	cout << Add(1.1, 2.2) << endl;
	return 0;
}
类型不同:一个整形一个浮点型但是函数名相同C++会自动匹配类型C却不能
2. 参数个数不同
#include<iostream>
using namespace std;
void f()
{
	cout << "f()" << endl;
}
void f(int a)
{
	cout << "f(int a)" << endl;
}
int main()
{
	f();
	f(10);
	return 0;
}
3. 参数类型顺序不同
#include<iostream>
using namespace std;
void f(int a, char b)
{
	cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
	cout << "f(char b, int a)" << endl;
}
int main()
{
	f(10, 'a');
	f('a', 10);
	return 0;
}
注意:是参数类型的顺序不同不是形参的名字不同
#include<iostream>
using namespace std;
void f(int a, char b)
{
	cout << "f(int a,char b)" << endl;
}
void f(int b, char a)
{
	cout << "f(int b, char a)" << endl;
}

请添加图片描述

注意:返回值不同不能构成重载
#include<iostream>
using namespace std;
void f(char a, int b)
{
	cout << "f(int a,char b)" << endl;
}
int f(char a, int b)
{
	cout << "f(int a, char b)" << endl;
}
int main()
{
	return 0;
}

请添加图片描述

4. 重载与缺省参数的碰撞擦出的火花
#include<iostream>
using namespace std;
//构成函数重载
void func(int a)
{
	cout << "void func(int a)" << endl;
}
void func(int a, int b = 1)
{
	cout << "void func(int a,int b)" << endl;
}
int main()
{
	func(1,2);
	//调用存在歧义
	func(10);
	return 0;
}

重载和缺省参数碰撞是可以构成重载的(参数个数不同),但是会出现调用歧义(当调用func(1,2)是不会出现问题的,但是调用func(10),编译器就不知道调用哪个因为两个都符合调用)

🌏1.2.C++支持函数重载的原理 – 名字修饰

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

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接,最终形成一个可执行程序

1. 对于C语言示例:

对于C语言来说,当经过预处理、编译、汇编、链接

//#include<iostream>
//using namespace std;
void func(int i, double d)
{
	//cout << "void func(int i, double d)" << endl;
}
void func(double d, int i)
{
	//cout << "double func(double d, int i)" << endl;
}
int main()
{
	func(1, 5.2);
    func(5.2, 1);
	return 0;
}
效果演示:

请添加图片描述

2. 对于C++示例:
#include<iostream>
using namespace std;
void func(int i, double d)
{
	//cout << "void func(int i, double d)" << endl;
}
void func(double d, int i)
{
	//cout << "double func(double d, int i)" << endl;
}
int main()
{
	func(1, 5.2);
    func(5.2, 1);
	return 0;
}
效果演示:

在这里插入图片描述

名字修饰:

先提前说明一下,这部分不懂得可以看C语言—程序环境和预处理(底层原理万字详解)

请添加图片描述

实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。那么怎么办呢?

  • 所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起。
  • 那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则
  • 使用g++修饰后的名字通过下面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】
1. 采用C语言编译器编译后结果:

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

2. 采用C++编译器编译后结果:

请添加图片描述

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

函数名修饰规则带入返回值,返回值不能构成重载
#include<iostream>
using namespace std;
int func(double d, int i)
{
	cout << "void func(int i, double d)" << endl;
	return 0;
}
void func(double d, int i)
{
	cout << "double func(double d, int i)" << endl;
}
int main()
{
	func(1.1, 1);
	func(1, 1.1);
	return 0;
}

请添加图片描述

3. 总结:
  • 通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。
  • 如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。

🌟二、引用

🌏2.1.引用的概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
比如:孙悟空,唐僧称为"悟空",江湖上人称"齐天大圣"。
类型& 引用变量名(对象名) = 引用实体;

示例:
void TestRef()
{
int a = 10;
int& ra = a;//<====定义引用类型
printf("%p\n", &a);
printf("%p\n", &ra);
}
效果演示:

请添加图片描述

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

🌏2.2.引用特性

  • 引用在定义时必须初始化
  • 一个变量可以有多个引用
  • 引用一旦引用一个实体,再不能引用其他实体
void TestRef()
{
1. 引用在定义时必须初始化
int a = 10;
// int& ra; // 该条语句编译时会出错

2. 一个变量可以有多个引用
int& ra = a;//给a取别名
int& rra = a;//给a取别名
int& raa = ra;//给b(a的别名)取别名也是可以的


3. 引用一旦引用一个实体,再不能引用其他实体(C++的引用不可以改变指向但是Java可以)
int x = 1;
b = x; 
//这里是赋值而不是把b变成x的别名
}

在这里插入图片描述

🌏2.3.常引用

void TestConstRef()
{
权限的放大:就相当于带上金箍圈的孙悟空(const)摘下了金箍圈变得肆无忌惮
const int a = 10;
//int& ra = a; // 该语句编译时会出错,a为常量 --- 权限的放大在这里去掉了const也就是去掉了金箍圈
const int& ra = a;--- 权限的平移:带上金箍圈无论是孙悟空还是齐天大圣它都有限制不会肆无忌惮


权限的缩小:本来是大闹天宫的齐天大圣被戴上了金箍圈(const)就有了限制
int x=10;
const int& y=x;


double d = 12.34;
//int& rd = d; // 该语句编译时会出错,类型不同
const int& rd = d;
在C/C++中有规定:发生类型转换,会产生一个临时变量,例如上面这一小段代码const int& rd = d,转换时会有一个int类型的临时变量,临时变量再给rd,但是临时变量具有常性int& rd = d这里就是权限的放大不能通过编译,所以这种是对的const int& rd = d

// int& b = 10; // 该语句编译时会出错,b为常量 - 不能变成常量对象的别名
const int& b = 10;--- 权限平移
}
注意:

在引用的过程中:

  1. 权限可以平移
  2. 权限可以缩小
  3. 权限不可以放大
示例:
#include<iostream>
using namespace std;
int func()
{
	int a = 0;
	return a;
}
int main()
{
	const int& ret = func();
	return 0;
}

请添加图片描述

🌏2.4.使用场景

1. 做参数/交换两个数值:
#include<iostream>
using namespace std;
void Swap(int& left, int& right)
{
	int tmp = left;
	left = right;
	right = tmp;
}
int main()
{
	int i = 3, j = 6;
	Swap(i, j);
	cout << i << endl;
	cout << j << endl;
	return 0;
}
效果演示:

请添加图片描述

2. 做返回值:
1. 传值返回:不是把n返回给ret,n在Count函数栈帧里面,函数调用结束栈帧也就销毁了

实际原理:是会生成一个临时变量(可能寄存器充当也可能其他方式),n会在返回值之前拷贝给临时变量,临时变量不会在Count函数的栈帧,一般是在寄存器或者上一层函数的栈帧

#include<iostream>
using namespace std;
int Count()
{
	int n = 0;
	n++;
	// ...
	return n;
}
int main()
{
	int ret = Count();
	return 0;
}
2. 传引用返回第一种:返回的是n的别名/n的引用

会出现类似野指针的危险:n都销毁了,在访问n的别名
问:n都销毁了还能访问它的别名吗?
答:可以,因为空间销毁并不是这块空间就没了而是被系统回收,就像酒店里的房间,退房后房间不会消失而是被回收你的入住权租给别人或者空着,而野指针就是退房后你还偷偷藏了房间的钥匙,然后偷偷跑进房间。但是这里不是野指针,返回n的别名是不合法的

#include<iostream>
using namespace std;
int& Count()
{
	int n = 0;
	n++;
	// ...
	return n;
}
int main()
{
	int ret = Count();
	cout << ret << endl;
	cout << ret << endl;
	return 0;
}

请添加图片描述

效果演示:

程序的结果有两种可能:1和随机值------>调用函数返回n的别名,当int ret=Count(),函数Count()栈帧已经销毁了,再去访问这块空间就会出现两种可能性第一种是1拷贝给ret,还有一种可能是随机值(取决于栈帧销毁后空间是否会被置成随机值取决于编译系统)请添加图片描述

3. 传引用返回第二种:

这种代表ret也是n的别名,第一次访问打印ret是1,第二次就变成了随机值为什么
知识点补充:cout是一个函数调用,(调用函数先传参)第一次先传参取到的还是1然后进行函数调用,Count函数的栈帧销毁,第一次函数调用占用的还是那块空间只不过可能比之前Count函数栈帧大或者小此时函数调用覆盖这块空间而ret还是这块空间的别名所以取到的就是一个随机值,但也不一定是随机值,当Count函数栈帧很大n在下面,就不会被覆盖

#include<iostream>
using namespace std;
int& Count()
{
	int n = 0;
	n++;
	// ...
	return n;
}
int main()
{
	int& ret = Count();
	cout << ret << endl;
	cout << ret << endl;
	return 0;
}
效果演示:

请添加图片描述

4. 例题及构图解析:
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;
    return 0;
}

在这里插入图片描述

3. 注意:

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

🌏2.5.传值、传引用效率比较

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

1. 值和引用作为函数参数的性能比较:
#include<iostream>
using namespace std;
#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(A)-time:" << end1 - begin1 << endl;
	cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{
	TestRefAndValue();
	return 0;
}
效果演示:

请添加图片描述

2. 值和引用的作为返回值类型的性能比较:
#include<iostream>
using namespace std;
#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;
}
效果演示:

请添加图片描述

通过上述代码的比较,发现传值和指针在作为传参以及返回值类型上效率相差很大

3. 总结:

传引用传参(任何时候都可以用)

  1. 提高效率
  2. 输出型参数(形参的修改,影响的实参)

传引用返回(出了函数作用域对象还在才可以用)

  1. 提高效率
  2. 修改返回对象(末尾彩蛋处有体现)

🌏2.6.引用和指针的区别

1. 在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间:
#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	int& ra = a;
	cout << "&a = " << &a << endl;
	cout << "&ra = " << &ra << endl;
	return 0;
}

在这里插入图片描述

2. 在底层实现上实际是有空间的,因为引用是按照指针方式来实现的:
#include<iostream>
using namespace std;
int main()
{
	int a = 0;
	int* p1 = &a;
	int& ref = a;
	++(*p1);
	++ref;
	return 0;
}

请添加图片描述

引用和指针的不同点:

引用和指针的不同点:

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

🌟三、末尾彩蛋(带你回溯时空联想之前)

1. C设计顺序表部分接口
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
struct SeqList
{
	int a[10];
	int size;
};
//读取第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;
}
int main()
{
	return 0;
}
2. C++设计顺序表部分接口
#include<iostream>
#include<assert.h>
#include<stdlib.h>
using namespace std;

struct SeqList
{
	int a[10];
	int size;
};
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;
}
效果演示:

请添加图片描述

  1. 读取i位置:减少了拷贝,返回此时位置的别名
  2. 修改i位置:数组中第i个位置的值出了作用域肯定还在,因为结构体在外面不在函数的栈帧里面所以存在,出了作用域不会销毁,得到它的别名后,通过赋值加加等就会修改
  3. 如果不用引用返回的就是它的临时拷贝打印是没有问题的修改却是不可以的因为临时对象具有常性不能修改

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

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

相关文章

Web 自动化神器 TestCafe—页面高级操作篇

♥ 前 言 在【Web 自动化神器 TestCafe — 页面基本操作篇】这篇文章中我们介绍了TestCafe页面交互的一些基本使用 Web 自动化神器 TestCafe — 页面基本操作篇 这篇文章接着上一篇来给大家介绍一下 TestCafe 页面交互的一些高级操作。 一、鼠标拖拽 鼠标拖拽鼠标拖拽 …

食品制造行业云MES系统解决方案

食品饮料行业大致可以分为初级产品加工、二次加工、食品制造、食品分装、调味品和饲料加工等几大类。由于处于产业链不同的位置&#xff0c;其管理存在一定的差异&#xff0c;那么食品行业的MES应该怎么建设呢&#xff1f; 食品饮料行业生产管理特点&#xff1a; 食品饮料行业…

matlab使用教程(21)—求函数最值

1. 求函数最优值 1.1求一元函数的最小值 如果给定了一个一元数学函数&#xff0c;可以使用 fminbnd 函数求该函数在给定区间中的局部最小值。例如&#xff0c;请考虑 MATLAB 提供的 humps.m 函数。下图显示了 humps 的图。 x -1:.01:2; y humps(x); plot(x,y) xlabel(x)…

NLP与大模型主题全国师资培训班落地,飞桨持续赋能AI人才培养

为了推动大模型及人工智能相关专业人员的培养&#xff0c;8月11日-8月13日&#xff0c;由中国计算机学会主办、机械工业出版社、北京航空航天大学、百度飞桨联合承办 “CCF群星计划之文心高校行- NLP与大模型”主题师资培训班&#xff08;以下简称培训班&#xff09;在北京天信…

react antd常见报错Each child in a list should have a unique “key“ prop

常见的一个报错内容&#xff1a;原因可能真的很奇怪&#xff0c;但是那就那么三四种情况&#xff0c;在此记录一下这个问题 console.js:213 Warning: Each child in a list should have a unique "key" prop. Check the render method of Panel. It was passed a chi…

4G工业路由器的功能与选型!详解工作原理、关键参数、典型品牌

随着工业互联网的发展,4G工业路由器得到越来越广泛的应用。但是如何根据实际需求选择合适的4G工业路由器,是许多用户关心的问题。为此,本文将深入剖析4G工业路由器的工作原理、重要参数及选型要点,并推荐优质的品牌及产品,以提供选型参考。 一、4G工业路由器的工作原理 4G工业…

gitee远程仓库——Git常用远程仓库托管服务

远程仓库 我们的代码不能总是放在本地&#xff0c;因为总是放在本地&#xff0c;一旦电脑出现故障&#xff0c;数据将丢失&#xff0c;怎么共享呢&#xff1f;这里我们需要一个服务器&#xff0c;我们可以把代码放到服务器上&#xff0c;然后让别人下载&#xff0c;这样我们既…

动力节点Java项目的开发原则与核心业务介绍

文章目录 一 项目开发原则 1.1 web开发项目的步骤&#xff1a; 1.2 crm的技术架构&#xff1a;客户关系管理技术框架 1.3 开发目的 1.4 软件公司的组织结构 1.5 软件开发的生命周期 1&#xff09;招标 2&#xff09;可行性分析 3&#xff09;需求分析 4&#xff09;…

Dockerfile文件详细

Dockerfile 是一个文本文件&#xff0c;里面包含组装新镜像时用到的基础镜像和各种指令&#xff0c;使用dockerfile 文件来定义镜像&#xff0c;然后运行镜像&#xff0c;启动容器。 dockerfile文件的组成部分 一个dockerfile文件包含以下部分&#xff1a; 基础镜像信息&…

python爬虫-网页数据提取

import requests #headers 网页右键->Network->最下面的User-Agent复制。 headers {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"} #你想要的网址 url &q…

基于大语言模型知识问答应用落地实践 – 知识库构建(上)

01 背景介绍 随着大语言模型效果明显提升&#xff0c;其相关的应用不断涌现呈现出越来越火爆的趋势。其中一种比较被广泛关注的技术路线是大语言模型&#xff08;LLM&#xff09;知识召回&#xff08;Knowledge Retrieval&#xff09;的方式&#xff0c;在私域知识问答方面可以…

HTTP协议(JavaEE初阶系列15)

目录 前言&#xff1a; 1.HTTP协议 1.1HTTP协议是什么 1.2HTTP协议的报文格式 1.2.1抓包工具的使用 1.2.2HTTP请求 1.2.3HTTP响应 2.HTTP请求 2.1首行的组成 2.2.1URL的组成 2.2认识“方法”&#xff08;method&#xff09; 2.2.1GET方法 2.2.2POST方法 2.2.3GET…

【AIGC】单图换脸离线版软件包及使用方法

云端再好&#xff0c;都不如放自己手里啊&#xff0c;想怎么就怎么玩。云端再好&#xff0c;都不如放自己手里啊&#xff0c;想怎么就怎么玩。 Roop作为一个新出的开源项目&#xff0c;配置起来还是有一定难度的。 我已经把各种依赖&#xff0c;模型&#xff0c;环境配置已经…

c++--动态规划回文串问题

1.回文子串 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给定一个字符串 s &#xff0c;请计算这个字符串中有多少个回文子字符串。 具有不同开始位置或结束位置的子串&#xff0c;即使是由相同的字符组成&#xff0c;也会被视作不同的子串。 示…

23-props详解

一. 什么是prop Prop定义: 组件上注册的一些 自定义属性 Prop作用: 想子组件传递数据 特点: 1. 可以传递 任意数量 的Prop 2. 可以传递 任意类型 的Prop 二. Props校验 思考: 组件的prop 可以乱传吗? 作用: 为组件的 prop 指定验证要求,不符合要求,控制台就会有提示错误 …

图神经网络与分子表征:2. 读懂SchNet

SchNet 在2018年的面世彻底引爆了神经网络势函数(NNP, Neural Network Potential)领域&#xff0c;虽然说NNP的开山鼻祖还要更早&#xff0c;但均未像 SchNet 这样真正被物理化学家接受&#xff0c;引发变革。 这篇博客浅浅记录下自己阅读SchNet代码的心得。2023年的今天&…

shell 脚本基础(四十三)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 1. 概念 2. 学习路径 2.1表达式 2.2 语句 2.3 函数 2.4 正则表达式 2.5 文件操作四剑客 二、表达式 1.shell 2.1 变量 2.2.1组成 2.2.2 类型 2.2.3 作用域…

二级评论列表功能

一&#xff1a;需求场景 我的个人网站留言列表在开发时&#xff0c;因为本着先有功能的原则。留言列表只有一级&#xff0c;平铺的。 当涉及多人回复&#xff0c;或者两个人多次对话后&#xff0c; 留言逻辑看着非常混乱。如下图 于是&#xff0c;我就打算将平铺的列表&#…

【数据备份、恢复、迁移与容灾】上海道宁与云祺科技为企业用户提供云数据中心容灾备份解决方案

云祺容灾备份系统支持 主流虚拟化环境下的虚拟机备份 提供对云基础设施 云架构平台以及 应用系统的全方位数据保护 云祺容灾备份系统规范功能 增强决策能力 高效恢复数据至可用状态 有效降低恢复成本 更大限度减少业务中断时间 保障业务可访问性 开发商介绍 成都云祺…

部署 Windows 域(一)

目录 简介 1. 部署 AD 前的准备 2. 部署 Windows 域的过程 2.1 安装域控制器 2.2 将客户机加入域 1.联机加入域 2.脱机加入域 简介 前面章节介绍了域的相关概念&#xff0c;以及工作组和域的主要区别&#xff0c;想要实现域环境&#xff0c;就必须部署至少一台域控制器。…