【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.h
  void Func(int a = 10);
  
  // a.cpp
  void 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++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载
如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分

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

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

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

相关文章

Linux - 线程互斥和互斥锁

文章目录 前言一、为什么要线程互斥原子性 二、互斥锁互斥锁的创建与销毁互斥锁进行互斥 前言 前几节课&#xff0c;我们学习了多线程的基础概念&#xff0c;这节课&#xff0c;我们来对线程互斥和互斥锁的内容进行学习。 一、为什么要线程互斥 首先我们要明白&#xff0c;对…

AOP切面编程

1.基本概念&#xff1a; AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向切面编程&#xff09;&#xff0c;跟oop面向过程编程相对&#xff0c;AOP一般用于将公共逻辑和业务逻辑进行拆分&#xff0c;可以减少代码间的耦合性。 有道翻译&#xff1a;AOP—面向切面…

jsp2024.3.21(4) html基础

一、实验目的 1、html 文件的基本结构&#xff1b; 2、html 的常用标记&#xff1b; <HTML> <HEAD> …… </HEAD> <BODY> …… </BODY> </HTML> 二、实验项目内容&#xff08;实验题目&#xff09; HTML常用标记 1&#xff0e;<…

C语言数据在内存中的存续:一篇文章让你秒懂基础!

JAMES别扣了-CSDN博客 &#x1f495;在校大学生一枚。对IT有着极其浓厚的兴趣 ✨系列专栏目前为C语言初阶、后续会更新c语言的学习方法以及c题目分享. &#x1f60d;希望我的文章对大家有着不一样的帮助&#xff0c;欢迎大家关注我&#xff0c;我也会回关&#xff0c;大家一起交…

LeetCode 热题 100 | 堆(一)

目录 1 什么是堆排序 1.1 什么是堆 1.2 如何构建堆 1.3 举例说明 2 215. 数组中的第 K 个最大元素 2.1 子树大根化 2.2 遍历所有子树 2.3 弹出栈顶元素 2.4 完整代码 菜鸟做题&#xff0c;语言是 C 1 什么是堆排序 1.1 什么是堆 堆的定义和分类&#xff…

为什么Hashtable不允许插入nuIl键和null值?

1、典型回答 浅层次的来回答这个问题的答案是&#xff0c;JDK 源码不支持 Hashtable 插入 value 值为 null&#xff0c;如以下 JDK 源码所示&#xff1a; 也就是 JDK 源码规定了&#xff0c;如果你给 Hashtable 插入 value 值为 null 就会抛出空指针异常。 并且看上面的 JDK …

如何搭建DolphinScheduler服务并结合内网穿透公网远程任务调度

文章目录 前言1. 安装部署DolphinScheduler1.1 启动服务 2. 登录DolphinScheduler界面3. 安装内网穿透工具4. 配置Dolphin Scheduler公网地址5. 固定DolphinScheduler公网地址 前言 本篇教程和大家分享一下DolphinScheduler的安装部署及如何实现公网远程访问&#xff0c;结合内…

Stable Diffusion WebUI 生成参数:宽度/高度/生成批次/每批数量/提示词相关性/随机种子

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 大家好&#xff0c;我是水滴~~ 本文将继续了解 Stable Diffusion WebUI 的生成参数&#xff0c;主要内容有&#xff1a;宽度、高度、生成批次、每批数量、提示词相关性、随机种子。希望能对你…

大模型主流微调训练方法总结 LoRA、Adapter、Prefix-tuning、P-tuning、Prompt-tuning 并训练自己的数据集

大模型主流微调训练方法总结 LoRA、Adapter、Prefix-tuning、P-tuning、Prompt-tuning 概述 大模型微调(finetuning)以适应特定任务是一个复杂且计算密集型的过程。本文训练测试主要是基于主流的的微调方法:LoRA、Adapter、Prefix-tuning、P-tuning和Prompt-tuning,并对…

STM32驱动CC1101时的正确配置和一些遇到的坑

项目背景 由于项目需要用到CC1101-Q1,所以买了CC1101的模块和驱动底板,插电脑上一发一收。串口调试助手查看接收端的数据,测试正常。 然后想用STM32来驱动其中的一块CC1101模块作为发送端,和另一个买来的接收端测试通信。找到一份STM32驱动CC1101Demo代码,分为软件模拟S…

Certum代码签名证书

代码签名证书是一种数字证书&#xff0c;用于验证软件开发者身份和保证软件完整性的技术。它的作用在于确保软件在传输和安装过程中没有被篡改或损坏&#xff0c;并且确认软件来自可信的开发者。通过代码签名证书&#xff0c;用户可以更放心地下载和安装软件&#xff0c;降低安…

【Linux】文件描述符 - fd

文章目录 1. open 接口介绍1.1 代码演示1.2 open 函数返回值 2. 文件描述符 fd2.1 0 / 1 / 22.2 文件描述符的分配规则 3. 重定向3.1 dup2 系统调用函数 4. FILE 与 缓冲区 1. open 接口介绍 使用 man open 指令查看手册&#xff1a; #include <sys/types.h> #include …

AI系统性学习06—开源中文语言大模型

1、ChatGLM ChatGLM-6B的github地址&#xff1a;https://github.com/THUDM/ChatGLM-6B ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型&#xff0c;基于 General Language Model (GLM) 架构&#xff0c;具有 62 亿参数。结合模型量化技术&#xff0c;用户可以在消费级…

透视未来工厂:山海鲸可视化打造数字孪生新篇章

在信息化浪潮的推动下&#xff0c;数字孪生工厂项目正成为工业制造领域的新宠。作为一名山海鲸可视化的资深用户&#xff0c;我深感其强大的数据可视化能力和数字孪生技术在工厂管理中的应用价值&#xff0c;同时我们公司之前也和山海鲸可视化合作制作了一个智慧工厂项目&#…

OceanBase生产环境安装部署的最优实践

关于生产环境&#xff0c;为了尽量确保性能和稳定性&#xff0c;我们比较建议采用标准化的配置进行部署&#xff0c;例如接下来会提到的服务初始化、日志管理和数据分盘等关键步骤。而在非生产环境中&#xff0c;如果条件满足&#xff0c;同样建议遵循规范部署的原则。 前期准备…

项目实战-开发工具入门/基本框架搭建/项目初始化/引入组件库

上周更新完了之前vue3的shopping项目&#xff0c;接下来&#xff0c;将会开启一个新的项目&#xff0c;效果是类似于移动端的一个伙伴匹配项目&#xff0c;今天这篇文章从需求分析到架构设计再到项目初始化&#xff0c;基本框架搭建几个部分来为大家详细介绍。 从这个项目开始…

YOLOV5 改进:替换backbone为Swin Transformer

1、前言 本文会将YOLOV5 backbone更换成Swin Transformer 具体为什么这样实现参考上文:YOLOV5 改进:替换backbone(MobileNet为例)-CSDN博客 这里只贴加入的代码 训练结果如下: 2、common文件更改 在common文件中加入下面代码: 这里是swin transformer的实现,参考:…

VMware部署银河麒麟遇到的问题记录

1. 解决VMware Workstation安装VMware Tools显示灰色的办法 1.关闭虚拟机; 2.在虚拟机设置分别设置CD/DVD、CD/DVD2和软盘为自动检测三个步骤; 3.再重启虚拟机,灰色字即点亮。 2.Linux安装vmTool

Pytest接口自动化测试框架搭建模板

auto_api_test 开发环境: Pycharm 开发语言&版本: python3.7.8 测试框架: Pytest、测试报告: Allure 项目源码Git地址 项目目录结构 api – 模仿PO模式, 抽象出页面类, 页面类内包含页面所包含所有接口, 并封装成方法可供其他模块直接调用config – 配置文件目录data…

打造高效自动化渗透测试系统:关键步骤与实践

随着当前网络安全威胁的不断扩展与升级&#xff0c;开展渗透测试工作已经成为广大企业组织主动识别安全漏洞与潜在风险的关键过程。然而&#xff0c;传统的人工渗透测试模式对测试人员的专业能力和经验水平有很高的要求&#xff0c;企业需要投入较大的时间和资源才能完成。在此…