【c++入门】命名空间,缺省参数与函数重载

Alt

🔥个人主页: Quitecoder

🔥专栏:c++笔记仓
Alt

朋友们大家好!本篇内容我们进入一个新的阶段,进入c++的学习!希望我的博客内容能对你有帮助!

目录

  • 1.c++关键字
  • 2.第一个c++代码
  • 3.命名空间
    • 3.1 namespace
    • 3.2命名空间使用
  • 4.c++中的输入输出
  • 5.缺省参数
      • 编译与链接过程
      • 函数与文件的关系
  • 6.函数重载
    • 6.1函数重载的的原理:名字修饰

1.c++关键字

C++总计63个关键字,C语言32个关键字

在这里插入图片描述
C++是一种与C语言紧密相关的编程语言。尽管它继承了C语言的许多特点,但C++引入了面向对象编程等概念,并增加了一些自己的特性和关键字来支持这些特性。比较C++和C语言的关键字,我们可以发现以下特征:

增加的关键字: C++增加了一些关键字来支持面向对象编程(如类、继承、多态等)和模板编程。例如,classpublicprotectedprivatevirtualfriendtemplatetypename等。这些关键字没有在C语言中。

类型增强:C++增加了一些用于类型安全和方便的关键字,如booltruefalseusingnamespace等。

异常处理:为了支持异常处理,C++引入了trycatchthrow等关键字。

新的转换操作符:C++提供了static_castdynamic_castconst_castreinterpret_cast等关键字进行类型转换,这是C语言中所没有的。

增强的存储类说明符:C++引入了mutablethread_local等存储类说明符。

模板编程:为了支持泛型编程,C++增加了templatetypename关键字。

新增运算符:C++还定义了如newdelete等用于动态内存管理的关键字,这些在C中通常通过库函数如malloc和free来实现。

特殊成员函数关键字:C++还有如defaultdelete等关键字,用于特殊成员函数的声明,这样设计是为了提供更好的控制。

C++相比C语言增加的关键字主要围绕面向对象编程、模板编程、异常处理、类型安全和内存管理等方面。这些新增加的特性和关键字使得C++成为一种更复杂但功能更强大的语言,这些目前我们不做过多解释,后期会逐个遇到

2.第一个c++代码

我们来看第一个c++代码:

#include<iostream>
using namespace std;
int main()
{cout<<"hello world"<<endl;return 0;
}

我们逐个来看:

  • #include<iostream>:这串代码是C++程序中的预处理指令,它的作用是告诉预处理器在实际编译之前包含标准输入输出流库iostream。这个库是C++标准库的一部分,为程序提供了输入输出功能,主要通过定义了一些流对象,例如std::cinstd::cout

我们可以发现在C++标准库中,标头文件通常不使用传统的.h后缀。这是C++标准制定时约定的一种风格,用来区分C++标准库的头文件和C风格或其他库的头文件。C语言的标准库头文件和一些旧的C++代码可能仍然使用.h后缀(例如stdio.h),但C++标准库头文件不遵循这一约定

  • using namespace std;: 这行代码是使用命名空间std的声明。std是标准C++库中定义的命名空间,其中包括了诸如cout、cin等通过这条声明,可以直接使用cout而不是std::cout来引用标准输出流对象,这个后面会讲到
  • cout<<"hello world"<<endl;
    • cout是一个输出流对象,用于发送数据到标准输出设备(如屏幕)
    • <<是插入操作符,用于将后面的数据发送到前面指定的流对象(这里是cout)
    • "hello world"是要输出的字符串。
    • endl是一个操控符,用于在输出流中插入一个换行符,然后刷新输出缓冲区,使得输出立即出现在目标设备上。这在某些情况下比简单使用\n换行符更有用,因为它确保了数据的即时输出

简单的分析完后,我们进行讲解

3.命名空间

在C/C++中,变量、函数和类都是大量存在的,这些变量、函数和类的名称将都存
在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的

在C语言中,实际上没有命名空间这一概念,所有的标识符(包括变量名、函数名等)都位于同一个全局命名空间中。因此,当两个不同的库或代码片段中存在同名的标识符时,就会发生命名冲突。以下是一个简单的示例说明这种情况:

#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{printf("%d\n", rand);
return 0;
}

编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”
在这里插入图片描述

这里存在的问题是,rand 是 <stdlib.h> 中已经定义的一个函数,该函数用于生成伪随机数。然而,在代码中,又定义了一个全局变量 rand 并赋值为10。这导致当在 main 函数中引用 rand 时,实际上引用的是定义的全局变量,而不是标准库中的 rand() 函数。

这正是命名冲突的一个例子:一个是标准库 <stdlib.h> 中的函数 rand(),另一个是用户定义的全局变量 rand。由于C语言中缺乏命名空间机制,这两个同名的实体会发生冲突

C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决

3.1 namespace

命名空间(Namespace)是C++中一种极为重要的特性,用来避免命名冲突,并且组织代码,使其易于维护和扩展。命名空间提供了一个范围,在这个范围内的名字(可以是变量、函数、结构体、类等)是可见的,但在范围外则不是。这允许开发者在不同的命名空间中使用相同的名字,而不会造成冲突。这特别对大型项目或者在集成多个库的时候非常有用

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员

namespace myrand
{// 命名空间中可以定义变量/函数/类型int rand = 10;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}
  • myrand为命名空间的名字
  • 命名空间可以包含变量、函数、结构、类等多种类型的成员。myrand命名空间内定义了一个名为rand的整型变量,并初始化值为10,这样做的好处是可以避免命名冲突

命名空间也可以嵌套定义,例如:

namespace N1
{
int a;
int b;
int Add(int left, int right)
{return left + right;
}namespace N2{int c;int d;int Sub(int left, int right){return left - right;}}
}

同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中

若我们再定义一个命名空间,取名仍为N1,编译器在编译时会将两个命名空间合并

一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中

3.2命名空间使用

方法一:加命名空间名称及作用域限定符

首先我们来介绍一个符号::,由两个冒号组成的一个符号叫做域作用限定符

注意,下面代码均在.cpp后缀的文件实现的

例如代码:

#include<stdio.h>
int a = 1;
int main()
{int a = 20;printf("%d\n", a);return 0;
}

这串代码,打印a时,首先会访问局部变量里面的a,如果我们想访问全局变量中的a,则需要使用全局命名空间操作符::来访问全局变量

在这里插入图片描述
::前缀指示编译器查找全局作用域中的a。因此,即使在main函数内部有一个同名的局部变量,使用::a还是可以访问到全局变量a,打印出的值为1

我们也可以访问自定义空间中的变量:

namespace s1 {int a = 1;
}
namespace s2 {int a = 2;
}
int main()
{int a = 20;printf("%d\n", a);printf("%d\n", s1::a);printf("%d\n", s2::a);return 0;
}

命名空间域将a封起来放在全局变量

编译器使用变量时,会进行搜索,首先会搜索局部域,再搜索全局域,我们想访问命名空间域里面的变量,就需要加命名空间名称及作用域限定符

这种特性在C++中非常有用,尤其是当局部变量的名称可能会与全局变量或者在其他命名空间中的变量重名时,可以通过这种方式明确指明想要使用的是哪个作用域中的变量

方法二:使用using将命名空间中某个成员引入

namespace N1
{int a=2;int b=3;
}
using N1::b;
int main()
{printf("%d\n",N1::a);printf("%d\n",b);return 0;
}

这里,N1命名空间包含了两个全局变量a和b,它们的作用域被限制在了N1命名空间内部。这意味着它们不能被直接访问,除非使用其命名空间名作前缀

接下来,通过using声明导入了N1命名空间中的b变量:

using N1::b;

这个声明使得在using声明所在作用域(在这个例子中,是全局作用域)内,可以直接访问b不需要N1::前缀。这种方式对于频繁访问某个命名空间中的特定成员而不想每次都写全命名空间名时非常有用

printf("%d\n", N1::a); // 输出2,通过完全限定名访问N1中的a
printf("%d\n", b);     // 输出3,通过using声明访问N1中的b
  • 对于N1::a的访问,因为没有用using语句声明a,所以需要使用完全限定名N1::a来访问它
  • 对于b,因为前面有using N1::b;声明,所以可以直接访问,不需要命名空间前缀

方法三:使用using namespace 命名空间名称 引入

namespace N1
{int a=2;int b=3;
}
using namespace N1;
int main()
{printf("%d\n",a);printf("%d\n",b);return 0;
}
using namespace N1;

这一语句告诉编译器,接下来的代码中如果遇到某个符号的名称与N1命名空间内的某个成员的名称匹配,就将这个符号解析为该命名空间内的成员,这使得在后续代码中,你可以不使用N1::前缀就直接访问a和b

4.c++中的输入输出

#include<iostream>
using namespace std;
int main()
{cout<<"hello world"<<endl;return 0;
}

再看这串代码

std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中

说明:

  • #include <iostream>这一行告诉编译器包含标准输入输出流库。这个库提供了输入输出的设施,其中就包括了cout, 使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std

  • cout是C++标准库中的一个对象,被封装在名为std的命名空间中,这里我们使用using namespace std,使得输出不需要加前缀,如果不用这串代码,则需要指定命名空间

输出格式如下:

#include<iostream>
int main()
{std::cout<<"hello world"<<std::endl;return 0;
}

cout通常用于向标准输出设备,通常是命令行(控制台)输出文本,endl是另一标准库对象,用于插入换行符并刷新输出缓冲区,也属于std命名空间

下面看这串代码:

#include <iostream>
using namespace std;
int main()
{int a;double b;char c;// 可以自动识别变量的类型cin>>a;cin>>b>>c;cout<<a<<endl;cout<<b<<" "<<c<<endl;return 0;
}
  • cin>>a;:这行代码从标准输入接受一个整数,并将其存储在变量a中。cin会根据提供的变量类型自动解释输入数据。我们假设用户输入了一个整数
  • cin>>b>>c;:这行代码首先从标准输入接受一个双精度浮点数,并将其存储在变量b中,接着接受一个字符并存储在c中。这演示了如何通过一个表达式从cin连续读取多个值

在这里插入图片描述

  • 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。C++的输入输出可以自动识别变量类型
  • <<是流插入运算符,>>是流提取运算符

5.缺省参数

在C++中,缺省参数(也称为默认参数)是函数或方法参数声明中所指定的默认值。如果在调用函数时未提供相应的参数,那么将自动使用这个默认值。这使得函数调用更加灵活

void Func(int a = 0)
{cout<<a<<endl;
}
int main()
{Func();     // 没有传参时,使用参数的默认值Func(10);   // 传参时,使用指定的实参
return 0;
}

这里打印结果为:

0
10

缺省参数有以下类型:

全缺省参数

void Func(int a = 10, int b = 20, int c = 30){cout<<"a = "<<a<<endl;cout<<"b = "<<b<<endl;cout<<"c = "<<c<<endl;}

在这里插入图片描述
注意,这里传参是按照顺序来的,不可以跳过某个参数传参

半缺省参数

void Func(int a, int b = 10, int c = 20){cout<<"a = "<<a<<endl;cout<<"b = "<<b<<endl;cout<<"c = "<<c<<endl;}

半缺省参数必须从右往左依次来给出,不能间隔着给

  //a.hvoid Func(int a = 10);// a.cppvoid Func(int a = 20){}

注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值

在C++中,当一个函数有缺省参数(默认参数)时,这个规则确保了程序的清晰性与一致性,避免了潜在的混淆。缺省参数意味着在函数调用中,如果没有提供某些参数,那么将自动使用这些参数的默认值。这句话的含义是,对于给定的函数,其缺省参数应该只在函数声明或定义中的一处指定,而不是两处同时指定

理解这句话的关键在于区分声明定义的概念:

  • 函数声明告诉编译器函数的名称、返回类型以及参数列表(类型、顺序和数量),但不涉及函数的具体实现。函数声明经常出现在头文件(.h)中

  • 函数定义:提供了函数的实际实现,它包括函数的主体,即函数被调用时将执行的具体代码。函数定义包含了函数声明的所有信息,并加上了函数体

为什么不能同时出现

如果在函数的声明和定义中都指定了缺省参数,可能会导致不一致性,使得理解和维护代码变得更加困难,编译器也可能不确定应该使用哪个版本的默认值,尤其是当声明和定义位于不同的文件时,为了避免这种情况,C++标准规定了缺省参数应当只在一个地方指定:

  • 如果函数声明在头文件中进行,那么就在头文件中的声明处指定缺省参数
  • 如果函数没有在头文件中声明(例如,完全在一个.cpp文件内定义),那么就在函数定义处指定缺省参数

最佳实践

最佳实践是在函数的声明中指定缺省参数,而在函数的定义中则省略这些默认值

// 函数声明,在头文件中
void example(int a, float b = 3.14); // 函数定义,在源文件中
void example(int a, float b) {// 函数体
}

在这个例子中,example函数的缺省参数只在函数声明中给出,而在定义时省略了默认值。这符合C++的最佳实践

当函数声明在头文件中进行,并在头文件中指定缺省参数,这与头文件的工作原理及C++编译过程有关

当函数声明在头文件中进行,并在头文件中指定缺省参数,这与头文件的工作原理及C++编译过程有关:

  • 预处理阶段:在这个阶段,编译器处理源代码中的预处理指令,如#include(将头文件内容展开至引用位置)、#define等。如果在头文件中指定了缺省参数,当进行#include预处理时,这些默认值也会被一并复制到每个包含了该头文件的源文件中,这确保了源文件在进入编译阶段时已经拥有了完整的函数声明信息

  • 编译阶段:编译器将预处理后的源代码转换成目标代码(通常是机器代码的一种中间形态)。如果函数的缺省参数在头文件中被声明,那么每个包含了该头文件的源文件都能正确地编译函数调用,因为它们都"看到"了相同的带有缺省参数的函数声明

  • 链接阶段:链接器将多个对象文件(目标代码)和库一起链接成最终的可执行文件。由于缺省参数已经在头文件中声明,并且该头文件被所有需要的源文件正确地包含,链接器不需要关心默认值的问题,因为这些默认值不影响函数的链接过程

我们这里扩展一下:

假如我现在有三个文件,stack.h包含函数的声明,stack.c包含函数的定义,test.c是一个测试函数所用的文件,先简单说明一下这些文件的作用:

  • stack.h(头文件):包含函数声明(也可能包含类型定义、宏定义等)。它的主要目的是提供一个接口的定义,以便其他文件在使用这些函数时,编译器能够了解到它们的存在及其接口
  • stack.c(源文件):包含函数的具体实现。这里编写了在stack.h中声明的函数的代码体
  • test.c(源文件):用于测试的代码文件,它会使用stack.h中声明的函数

编译与链接过程

  1. 预处理:对于每个.c文件,编译过程从预处理开始。预处理器会处理以#开头的指令,例如#include "stack.h"会将stack.h中的内容文本上粘贴到stack.ctest.c文件中,这样stack.ctest.c就可以看到这些函数声明了

  2. 编译:编译器接着编译每个.c源文件,将它们转换成目标代码(通常是机器代码的一种中间形态,称为目标文件,扩展名为.o.obj)。此时,编译器确保源代码符合语法规则,对每个源文件进行类型检查,确保所有函数调用都符合其声明但还不解决跨文件的函数引用问题。例如,stack.c被编译成stack.otest.c被编译成test.o

  3. 链接:一旦所有的源文件被编译成目标文件,链接器(linker)负责将这些目标文件以及必要的库文件链接成一个单一的可执行文件。在链接过程中,如果test.c(对应的是test.o)调用了stack.c中(对应的是stack.o)的函数,链接器负责“修补”这些调用,使得test.o中的调用可以正确地连接到stack.o中定义的函数上,链接器确保所有外部引用都能正确解析到它们所引用的实体。

函数与文件的关系

  • stack.h中声明的函数,让其他源文件知道这些函数的存在、它们的参数以及返回值类型。stack.h扮演了接口的角色。
  • stack.c提供了stack.h中声明的函数的具体实现。test.c作为使用这些函数的客户端代码,通过#include "stack.h"能够调用这些函数。
  • 编译过程中,test.cstack.c分别被编译成中间的目标文件。这些目标文件中的函数调用尚未解析到具体的地址
  • 在链接过程,链接器解析这些调用,使得从test.o中的调用可以正确地定位到stack.o中的函数定义,从而生成一个完整的可执行文件,所有的函数调用都被正确地解析和连接,这个地址修正的过程也叫做重定位

接下来我们所讲解的函数重载与上述内容也有所关联

6.函数重载

函数重载是C++语言的一个特性,它允许在同一作用域内声明几个具有相同名字的函数,只要这些函数的参数列表不同。这个机制让程序员可以为执行类似操作但需要处理不同数据类型或参数数量的函数提供统一的接口

参数不同

#include <iostream>
using namespace std;
void print(int i) {cout << "Printing int: " << i << endl;
}void print(double f) {cout << "Printing float: " << f << endl;
}int main() {print(1);             // 调用 print(int)print(3.14);          // 调用 print(double)return 0;
}

参数个数不同

void f()
{cout << "f()" << endl;
}
void f(int a)
{cout << "f(int a)" << endl;
}

参数顺序不同

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

6.1函数重载的的原理:名字修饰

C++支持函数重载的原理,在很大程度上依赖于一种被称为**名字修饰(Name Mangling)**的过程。这种机制使得编译器能够区分同名但参数列表不同的函数,从而支持函数重载

名字修饰是什么?

名字修饰是编译器自动进行的一种处理过程,它将C++源代码中的函数名和变量名转换成包含更多信息的唯一标识符。这些信息通常包括函数的参数类型、参数数量等,甚至可能包括所属的类名(对于类成员函数),通过这种方式,每个重载的函数都会被赋予一个独一无二的名字,确保链接器在最后链接程序的时候能够区分它们

C++中允许函数重载,也就是允许同一个作用域内存在多个同名函数,只要它们的参数列表不同。但在编译成目标代码后,所有的函数名和变量名都必须区分开来,确保每个函数调用都能显式地映射到正确的函数体上。名字修饰通过在函数名中编码函数参数类型等信息,实现了这一点

名字修饰实例

比如,考虑下面的C++函数重载:

void print(int i);
void print(double d);

在经过编译器处理后,这些函数可能会分别被修饰为(名字修饰的具体结果依赖于编译器):

  • print(int) 可能被修饰为 _print_i
  • print(double) 可能被修饰为 _print_d

这样,尽管这两个函数原名相同,但在编译器处理后它们获得了不同的名字,使得编译后的代码中对这些函数的引用能够清晰地区分开来

名字修饰使得C++能够有效地支持函数重载和模板等功能,虽然这种机制在编程过程中对程序员是透明的,但理解其背后的原理对于深入掌握C++语言是有帮助的。同时,这也是C++与其他语言例如C的一个重要区别:C语言不支持函数重载,部分原因就在于它没有采用类似的名字修饰机制

我们来看linux环境下不同编译器编译相同代码的结果:

采用C语言编译器编译后结果
在这里插入图片描述
在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变

采用C++编译器编译后结果
在这里插入图片描述
在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中

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

本节内容到此结束,感谢大家阅读!!

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

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

相关文章

CTF-辨别细菌

题目描述&#xff1a;try your best to find the flag. 进入靶场后发现是一个游戏&#xff0c;需要全部答对才可以得到最后的flag 查看了一下源码&#xff0c;发现有一个答案模板的模块 尝试解释一下代码 <!-- 答案模版 --> <script id"template_game_pi…

数据结构/C++:红黑树

数据结构/C&#xff1a;红黑树 概念实现基本结构插入uncle为红色节点uncle为黑色节点 总代码展示 概念 红黑树是一种二叉搜索树&#xff0c;一般的二叉搜索会发生不平衡现象&#xff0c;导致搜索效率下降&#xff0c;于是学者们开始探索如何让二叉搜索树保持平衡&#xff0c;这…

Agent驱动的RPA——实在Agent(智能体):自动化时代的新引擎

随着人工智能和机器学习技术的快速发展&#xff0c;智能Agent在 RPA领域扮演了革命性的角色。 Agent驱动的RPA不仅实现了传统规则导向自动化工具的功能升级&#xff0c;而且通过引入自主、智能决策与协作能力&#xff0c;为现代企业带来了更高程度的灵活性与智能化水平。随着数…

第1章 计算机系统概述

王道学习 1.1 操作系统的基本概念 1.1.1 操作系统的概念 1.1.2 操作系统的特征 操作系统是一种系统软件&#xff0c;但与其他系统软件和应用软件有很大的不同&#xff0c;它有自己的特殊性即基本特征。操作系统的基本特征包括并发、共享、虚拟和异步。这些概念对理解和掌握…

kail linux破解密码--- 详细过程(配合图文让你看了就会)

1.准备工作 1.vmware虚拟机 2.kali的系统 3.无线网卡一张(这个是必须的我买的是30多块) 4.这里为了实验&#xff0c;和直观的看到效果&#xff0c;用手机开了一个wifi然后使用kali进行破解 2.下载kali然后安装到虚拟机vmware 直接在官网下载 Get Kali | Kali Linux 我选…

WebXR实践——利用aframe框架浏览器展示全景图片

一、效果 话不多说&#xff0c;先上效果 二、代码 index.html <!DOCTYPE html> <html><head><meta charset"utf-8"><title>360&deg; Image</title><meta name"description" content"360&deg; Imag…

【机器学习】深入解析线性回归模型

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

高精度铸铁平台制造工艺有多精细——河北北重机械

高精度铸铁平台制造工艺通常包括以下几个步骤&#xff1a; 材料准备&#xff1a;选择合适的铸铁材料&#xff0c;并确保其质量符合要求。常用的铸铁材料包括灰铸铁、球墨铸铁等。 模具制造&#xff1a;根据平台的设计要求&#xff0c;制造适用的模具。模具一般由砂型、金属模具…

【python】flask基于cookie和session来实现会话控制

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

【开源-土拨鼠充电系统】鸿蒙 HarmonyOS 4.0 App+微信小程序+云平台

✨本人自己开发的开源项目&#xff1a;土拨鼠充电系统 ✨踩坑不易&#xff0c;还希望各位大佬支持一下&#xff0c;在Gitee或GitHub给我点个 Start ⭐⭐&#x1f44d;&#x1f44d; ✍Gitee开源项目地址&#x1f449;&#xff1a;https://gitee.com/cheinlu/groundhog-charging…

力扣Lc19--- 268. 丢失的数字(java版)-2024年3月20日

1.题目描述 2.知识点 &#xff08;1&#xff09;比如数组里面有n个数&#xff0c;然后计算这n个数的总和(用等差求和数列计算&#xff09;,然后减去数组的和&#xff0c;用总和减去数组和即为所得 &#xff08;2&#xff09;加强型 for 循环&#xff08;也称为 for-each 循环&…

单片机--数电(4)

触发器 数字电路中&#xff1a;分组合逻辑电路与时序逻辑电路两大类 组合逻辑电路的基本单元是门电路&#xff08;与或非等一些门电路&#xff09; 时序逻辑电路的基本单元是触发器 触发器与门电路的区别 门电路某一时刻的输出信号完全取决于该时刻的输入信号&#xff0c;…

销售数据分析怎么做?用好这5个数据分析方法与模型就足够了。

企业经营其实简单来说就是做买卖&#xff0c;有了买卖自然就产生了销售数据&#xff0c;那怎么能让这些销售数据产生价值呢&#xff1f;答案就是数据分析。通过对销售数据的分析&#xff0c;可以帮助企业及时洞察市场动向&#xff0c;发现企业销售过程中的问题&#xff0c;调整…

ResNet《Deep Residual Learning for Image Recognition》

ResNet论文学习 引言Deep Residual Learning 深度残差学习网络结构 总结代码复现 引言 深度网络自然地以端到端的多层方式集成低/中/高级特征和分类器&#xff0c;特征的“级别”可通过堆叠层的数量来丰富 随着网络层数加深&#xff0c;提取的特征越强&#xff0c;但是 网络…

表情识别数据集

表情视频数据集 在许多的研究中,研究者通常会把人脸表情识别区分为静态的人脸表情识别(static facial emotion recognition)和动态的人脸表情识别(dynamic facial emotion recognition)。前者希望通过单张图片辨别人的表情从而达到识别人情绪的目的,而后者希望感知视频/…

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程

在讲进程之前首先就是需要去回顾一下我们之前学的操作系统是干嘛的&#xff0c;首先操作系统是一个软件&#xff0c;它是对上提供一个良好高效&#xff0c;稳定的环境的&#xff0c;这是相对于用户来说的&#xff0c;对下是为了进行更好的软硬件管理的&#xff0c;所以操作系统…

TinyEMU源码分析之虚拟机初始化

TinyEMU源码分析之虚拟机初始化 1 初始化结构参数2 配置RAM地址空间3 初始化设备4 拷贝BIOS和Kernel5 手动写入5条指令6 体验第一条指令的执行 本文属于《 TinyEMU模拟器基础系列教程》之一&#xff0c;欢迎查看其它文章。 本文中使用的代码&#xff0c;均为伪代码&#xff0c…

vue2使用webSocket双向通讯

基于webSocket实现双向通信&#xff0c;使用webworker保持心跳。 由于浏览器的资源管理策略会暂停或限制某些资源的消耗&#xff0c;导致前端心跳包任务时效&#xff0c;后端接收不到webSocket心跳主动断开&#xff0c;因此需要使用webworker保持心跳 引入webworker npm insta…

关于安卓调用文件浏览器(一)打开并复制

背景 最近在做一个硬件产品&#xff0c;安卓应用开发。PM抽风&#xff0c;要求从app打开文件浏览器&#xff0c;跳转到指定目录&#xff0c;然后可以实现文件复制粘贴操作。 思考 从应用开发的角度看&#xff0c;从app打开系统文件浏览器并且选择文件&#xff0c;这是很常见…

.NET Framework 服务实现监控可观测性最佳实践

环境信息 系统环境&#xff1a;Windows Server开发语言&#xff1a;.NET Framework > 4.6.1APM探针包&#xff1a;ddtrace 准备工作 安装 Datakit 主机部署&#xff1a; 主机安装 - 观测云文档 打开采集 APM 采集器 Windows 主机配置 # 到如下路径&#xff0c;把ddtr…