【C++】构造函数、初始化列表,析构函数,拷贝构造函数,运算符重载

 注:本博客图片来源于学习笔记: 学习笔记icon-default.png?t=N7T8https://gitee.com/box-he-he/learning-notes

完整思维导图请前往该博主码云下载。


目录

 注:本博客图片来源于学习笔记: 学习笔记https://gitee.com/box-he-he/learning-notes

完整思维导图请前往该博主码云下载。

一、构造函数

构造函数的形式及其使用:

初始化列表:

explicit关键字

二、析构函数

1 .概念

2. 特性

析构函数的调用顺序

三、拷贝构造函数

特性:

四、运算符重载(部分)

1、概念

2、赋值运算符重载

3、前置++和后置++的实现


 

一、构造函数

构造函数是一种特殊的成员函数,在创建对象时自动调用,用于初始化对象的成员变量和执行其他必要的操作。它的名称与类名相同,没有返回类型,并且可以被重载。

构造函数有以下几个重要的特点:

  1. 构造函数的名称与类名相同,包括大小写和命名空间。
  2. 构造函数没有返回类型。
  3. 构造函数可以被重载,即可以定义多个具有不同参数列表的构造函数。
  4. 构造函数可以有默认参数,从而允许在创建对象时省略某些参数。
  5. 构造函数可以有任意数量的初始化列表,用于按照指定顺序初始化对象的成员变量。
  6. 构造函数可以访问类的所有成员变量和成员函数。
  7. 构造函数在创建对象时自动调用,无需手动调用。
  8. 对象的整个生命周期只调用一次。

构造函数主要用于以下几个方面(功能):

  1. 初始化成员变量:构造函数通过参数或初始化列表来初始化对象的成员变量,确保对象在创建时具有特定的初始值。
  2. 分配内存或资源:如果对象需要动态分配内存或管理其他资源(如文件句柄),构造函数可以在创建对象时进行相应的操作,从而确保对象可以正确地使用这些资源。
  3. 执行必要的操作:有时候,创建对象可能需要执行一些必要的操作,比如打开文件等,构造函数可以在创建对象时执行这些操作。

需要注意以下几点:

  1. 一个类可以有多个构造函数,它们具有不同的参数列表。这被称为构造函数的重载。
  2. 如果没有显式地定义构造函数,编译器会自动生成一个默认构造函数,但它只会对自定义类型变量进行默认初始化,对内置类型(int, double, float等)无法初始化。
  3. 编写构造函数时应该根据类的需求来初始化成员变量,并且可以根据需要执行其他必要的操作。
  4. 如果自定义了构造函数,编译器将不再生成默认构造函数。如果需要同时拥有默认构造函数和自定义构造函数,可以提供默认参数或者显式定义一个无参数的默认构造函数。

构造函数的形式及其使用:

默认构造函数包括:1、无参构造函数;2、全缺省的构造函数;3、编译器默认生成的构造函数 

当用户自己定义构造函数时 ,必须存在一个默认构造函数。

构造函数的使用:

 class Date{public:// 1.无参构造函数(默认构造函数)Date(){}// 2.带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}// 3.全缺省的构造函数(默认构造函数)Date(int year = 2024, int month = 2, int day = 6){_year = year;_month = month;_day = day;}// 4.编译器默认生成的构造函数(默认构造函数)private:int _year;int _month;int _day;};void TestDate(){Date d1; // 调用无参构造函数Date d2(2015, 1, 1); // 调用带参的构造函数// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象// warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)Date d3();}

需要注意的是全缺省的构造函数和无参的构造函数都属于默认构造函数,不能同时存在。

同时 函数2 与 函数3 无法构成函数重载,会造成函数的重定义,也无法同时存在。

 补充:由于编译器默认生成的构造函数无法对内置类型进行初始化,在C++11标准中,对此引入了解决方案:在变量声明时可以为其提供默认值。

 class Date{private:int _year = 2024;int _month = 2;int _day = 6;};void TestDate(){Date d; // 此时d的私有成员初始化为2024/2/6}

 

初始化列表:

1、基本形式

初始化列表:以一个 冒号开始 ,接着是一个以 逗号分隔的数据成员列表 ,每个 " 成员变量 " 后面跟
一个 放在括号中的初始值或表达式。
class Date
{
public:
Date(int year, int month, int day): _year(year), _month(month), _day(day){}private:
int _year;
int _month;
int _day;
};
【注意】
1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
  1. 引用成员变量
  2. const成员变量
  3. 自定义类型成员(且该类没有其默认构造函数时)        
class A
{
public:A(int a):_a(a){}
private:int _a;
};
class B
{
public:B(int a, int ref):_aobj(a), _ref(ref), _n(10){}
private:A _aobj;  // 没有默认构造函数的自定义类型int& _ref; // 引用const int _n; // const 
};

特性:

1、即使不在初始化列表中初始化自定义类型成员,其也会在初始化列表中隐式地调用其构造函数进行初始化。

2、初始化列表的执行顺序是其在类中的声明顺序,与初始化列表中的顺序无关。

explicit关键字

explicit 是一个关键字,用于修饰单参数构造函数,它可以防止编译器进行隐式的类型转换。在 C++ 中,当我们定义一个单参数构造函数时,编译器会自动进行隐式类型转换,将参数类型转换为目标类型,然后调用该构造函数来创建对象。而使用 explicit 关键字修饰的构造函数将被标记为禁止隐式类型转换。

下面是两个具体的示例来说明 explicit 关键字的作用:

1、单参构造函数

class MyClass {
public:explicit MyClass(int x) : value(x) {}int getValue() const {return value;}private:int value;
};int main() {MyClass obj1(5);       // 直接调用带有 int 参数的构造函数int val1 = obj1.getValue();MyClass obj2 = 10;    // 编译错误!禁止隐式类型转换int val2 = obj2.getValue();return 0;
}

在上述示例中,MyClass 类定义了一个带有单参数的构造函数,并使用 explicit 关键字进行修饰。这意味着我们只能通过显式地调用构造函数来创建对象,而不能进行隐式的类型转换。在 main 函数中,我们可以看到以下几点:

  1. 创建 obj1 对象时,我们直接调用了构造函数,不会发生隐式类型转换。这是合法的。

  2. 尝试使用 obj2 = 10; 进行从 int--->MyClass 隐式类型转换时,编译器会抛出错误。因为我们使用了 explicit 关键字,禁止隐式类型转换。

2、半缺省的构造函数

class MyClass {
public://虽然有多个参数,但是创建对象时后两个参数可以不传递,使用explicit修饰,// 不具有类型转换作用,编译不通过explicit MyClass(int x, int y = 1, int z = 1) : value(x), data(y), temp(z){}int getValue() const {return value;}private:int value;int data;int temp;
};int main() {MyClass obj1(5);       // 直接调用带有 int 参数的构造函数int val1 = obj1.getValue();MyClass obj2 = 10;    // 编译错误!禁止隐式类型转换int val2 = obj2.getValue();return 0;
}

二、析构函数

1 .概念

通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的?              

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由    

编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作

【注意】:析构函数只负责销毁占用的额外资源,即额外申请的内存空间,例如:malloc,new等。而对象本身,如果定义在函数中,则其本身存在于栈区中,随着函数的栈帧一同销毁,与析构函数无关。

2. 特性

析构函数是特殊的成员函数,其特征如下:

1. 析构函数名是在类名前加上字符 ~。

2. 无参数无返回值类型。

3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构

函数不能重载

4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;}void Push(DataType data){// CheckCapacity();_array[_size] = data;_size++;}//析构函数~Stack(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}
private:DataType* _array;int _capacity;int _size;
};
void TestStack()
{Stack s;s.Push(1);s.Push(2);
}

 

析构函数的调用顺序

  


三、拷贝构造函数

拷贝构造函数(Copy Constructor)是一种特殊的构造函数,它接受一个对象作为参数,用于创建一个新的对象,这个新对象与原始对象具有相同的值。

在C++中,如果我们没有显式定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数。默认拷贝构造函数执行的是逐个成员的拷贝,将源对象的每个成员变量的值复制给新创建的对象。

以下是一个简单的示例来说明拷贝构造函数的用法:

class MyClass {
public:int value;// 拷贝构造函数MyClass(const MyClass& other) {value = other.value;}
};int main() {MyClass obj1;obj1.value = 10;MyClass obj2(obj1);  // 使用拷贝构造函数创建新对象// 或者 MyClass obj2 = obj1;return 0;
}

在上述示例中,我们定义了一个名为 MyClass 的类,并在其中定义了一个拥有一个整数成员变量 value 的对象。然后我们在 main 函数中创建了两个对象 obj1 和 obj2

  • obj1 是通过默认构造函数创建的,并将 value 设置为 10。

  • obj2 是通过拷贝构造函数创建的,它的参数是另一个 MyClass 对象 obj1。在拷贝构造函数中,我们将 obj1 的值复制给了 obj2

需要注意的是,拷贝构造函数的参数应该是一个 const 引用(const MyClass& other),以确保不会修改被传递的源对象。

拷贝构造函数在以下情况下会被隐式调用:

  1. 通过赋值运算符(=)进行对象的初始化。
  2. 将一个对象作为函数的参数传递给另一个对象。
  3. 从一个函数返回对象时。

需要注意的是,当类中包含指针成员变量时,需要手动定义拷贝构造函数,以确保指针指向独立的内存,避免浅拷贝引发的指针悬挂问题。

 

特性:

1. 拷贝构造函数是构造函数的一个重载形式

2. 拷贝构造函数的参数只有一个必须是类类型对象的引用,使用传值方式编译器直接报错
因为会引发无穷递归调用。
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// Date(const Date& d)   // 正确写法Date(const Date d)   // 错误写法:编译报错,会引发无穷递归{_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;Date d2(d1);return 0;
}

 

 为什么值传递会引起无穷递归呢?为什么引用不会呢?

  答:假如参数不是引用,是值传递,那么传递给函数的值其实就是实参的一个临时拷贝,那在对实参进行临时拷贝时还是需要再次去调用我Date类里的拷贝构造函数,由于一直进行的是值传递,所以这个过程是无限递归的。但是如果拷贝构造函数的参数是对实参的引用,就不需要对实参再进行临时拷贝。引用是实参的一个别名,他们指向的也是同一块内存,所以不需要传递值,而是通过实参的引用来对实参的内存进行读写。

3. 若未显式定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储按

    字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝

class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time(const Time& t){_hour = t._hour;_minute = t._minute;_second = t._second;cout << "Time::Time(const Time&)" << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};
int main()
{Date d1;// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构//造函数Date d2(d1); // Date d2 = d1; 也是默认调用的拷贝函数return 0;
}

 【注意】:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝构造函数完成拷贝的。

4. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?

当然像日期类这样的类是没必要的。

但是对于初始化时成员需要额外申请内存的类,此时我们使用默认拷贝函数会发生程序崩溃,这时我们必须手动创建一个拷贝构造函数进行深拷贝。例如下面的栈class Stack;

typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}_size = 0;_capacity = capacity;}// 如果我们在这只是进行简单的值拷贝,程序将会崩溃Stack(const Stack& s){_array = new DataType[_capacity];memcpy(_array, s._array, _size * sizeof(DataType));_size = s._size;_capacity = s._capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}

 

【注意】:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请
时,则拷贝构造函数是一定要写的,否则就是浅拷贝。
 

5. 拷贝构造函数典型调用场景:     

  • 使用已存在对象创建新对象

  • 函数参数类型为类类型对象

  • 函数返回值类型为类类型对象

class MyClass {
public:int value;// 拷贝构造函数MyClass(const MyClass& other) {value = other.value;}
};MyClass Test(const MyClass obj3)
{MyClass temp;return temp; // 函数返回值类型为类类型对象// 由于temp为局部变量,在函数结束后不存在,所以需对temp进行临时拷贝,// 返回值的实质是temp的一份临时拷贝
}int main() {MyClass obj1;obj1.value = 10;MyClass obj2(obj1);  // 或者 MyClass obj2 = obj1;使用已存在的对象创建新对象Test(obj2);          // 函数的参数类型为类类型对象return 0;
}

四、运算符重载(部分)

1、概念

C++ 为了增强代码的可读性引入了运算符重载 运算符重载是具有特殊函数名的函数 ,也具有其
返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字 operator 后面接需要重载的运算符符号
函数原型: 返回值类型  operator 操作符 ( 参数列表 )
【注意】:
  1. 不能通过连接其他符号来创建新的操作符:比如operator@
  2. 重载操作符必须有一个类类型参数
  3. 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  4. 作为类成员函数重载时,其形参看起来比操作数数目少 1 ,因为成员函数的第一个参数为隐
    藏的 this
  5. .* :: sizeof ?: . 注意以上5个运算符不能重载。

2、赋值运算符重载


1、重载运算符的格式

  • 参数类型:const T&,传递引用可以提高传参效率

  • 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值

  • 检测是否自己给自己赋值

  • 返回*this :要复合连续赋值的含义

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}
private:int _year;int _month;int _day;
};

 

2. 赋值运算符只能重载成类的成员函数不能重载成全局函数

【原因】:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现
一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值
运算符重载只能是类的成员函数。

【注意】:如果需要在全局中重载其他运算符,需要给两个参数。因为只有类的非静态成员函数具有this指针,全局函数没有。

3. 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。

【注意】:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符
重载完成赋值。
 

3、前置++和后置++的实现

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// 前置++:返回+1之后的结果// 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率Date& operator++(){_day += 1;return *this;}// 后置++:// 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载// C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器//自动传递// 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存//一份,然后给this + 1// 而temp是临时对象,因此只能以值的方式返回,不能返回引用Date operator++(int){Date temp(*this);_day += 1;return temp;}
private:int _year;int _month;int _day;
};int main()
{Date d;Date d1(2022, 1, 13);d = d1++; // d: 2022,1,13 d1:2022,1,14d = ++d1; // d: 2022,1,15 d1:2022,1,15return 0;
}

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

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

相关文章

2024无参考图像的清晰度评价方法

无参考图像质量评价算法 无参考图像质量评价是指参考图像不存在的情况下&#xff0c;直接计算失真图像的视觉质量。根据无参考图像质量评价模型在计算图像视觉质量时是否需要图像的主观分数来进行训练&#xff0c;无参考图像质量评价算法可分为基于监督学习的无参考图像质量评价…

2024-02-06 TCP/UDP work

1. 画出TCP三次握手和四次挥手的示意图&#xff0c;并且总结TCP和UDP的区别 三次握手&#xff1a; 4次挥手&#xff1a; tcp/udp区别 TCP 1. 稳定&#xff0c;提供面向连接的&#xff0c;可靠的数据传输服务 2. 传输过程中&#xff0c;数据无误、数据无丢失、数据无失序、…

IDEA 配置以及一些技巧

1. IDEA设置 1.1 设置主题 1.2 设置字体和字体大小 1.3 编辑区的字体用ctrl鼠标滚轮可以控制大小 1.4 自动导包和优化多余的包 1.5 设置编码方式 1.6 配置 maven 1.7 设置方法形参参数提示 1.8 设置控制台的字体和大小 注意&#xff1a;设置控制台字体和大小后需要重启IDEA才会…

第1章 认识Flask

学习目标 了解Flask框架&#xff0c;能够说出Flask框架的发展史以及特点 熟悉隔离Python环境的创建方式&#xff0c;能够独立在计算机上创建隔离的Python环境 掌握Flask的安装方式&#xff0c;能够独立在计算机上安装Flask框架 掌握PyCharm配置隔离环境的方式&#xff0c;能…

【C++】基础知识讲解(命名空间、缺省参数、重载、输入输出)

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;http://t.csdnimg.cn/eCa5z 目录 命名空间 命名空间的定义 命名空间的使用 命名空间的嵌套使用 C输入&输出 std命名空间的使用惯例&…

C语言第二十弹---指针(四)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 指针 1、字符指针变量 2、数组指针变量 2.1、数组指针变量是什么&#xff1f; 2.2、数组指针变量怎么初始化 3、⼆维数组传参的本质 4、函数指针变量 4.1…

Rust开发WASM,浏览器运行WASM

首先需要安装wasm-pack cargo install wasm-pack 使用cargo创建工程 cargo new --lib mywasm 编辑Cargo.toml文件&#xff0c;修改lib的类型为cdylib&#xff0c;并且添加依赖wasm-bindgen [package] name "mywasm" version "0.1.0" edition "…

二进制安全虚拟机Protostar靶场(8)heap3 Fastbins unlink exploit

前言 这是一个系列文章&#xff0c;之前已经介绍过一些二进制安全的基础知识&#xff0c;这里就不过多重复提及&#xff0c;不熟悉的同学可以去看看我之前写的文章 heap3 程序静态分析 https://exploit.education/protostar/heap-three/#include <stdlib.h> #include …

故障诊断 | 一文解决,TCN时间卷积神经网络模型的故障诊断(Matlab)

效果一览 文章概述 故障诊断 | 一文解决,TCN时间卷积神经网络模型的故障诊断(Matlab) 模型描述 时间卷积神经网络(TCN)是一种用于序列数据建模和预测的深度学习模型。它通过卷积操作在时间维度上对序列数据进行特征提取,并且可以处理可变长度的输入序列。 要使用TCN进行…

3D室内虚拟灭火体验为预防火灾提供全新方案

室内火灾常见于充电器未拔、电动车、油锅起火及煤气泄露等原因&#xff0c;由于室内空间小、易燃物多&#xff0c;因此极易造成较大的人员财产损失&#xff0c;3D仿真还原技术、通过1&#xff1a;1模拟还原火灾发生全过程&#xff0c;火灾VR安全培训提供全方位、真实感强的模拟…

FlinkSql 窗口函数

Windowing TVF 以前用的是Grouped Window Functions&#xff08;分组窗口函数&#xff09;&#xff0c;但是分组窗口函数只支持窗口聚合 现在FlinkSql统一都是用的是Windowing TVFs&#xff08;窗口表值函数&#xff09;&#xff0c;Windowing TVFs更符合 SQL 标准且更加强大…

Java中JVM常用参数配置(提供配置示例)

目录 前言一、内存参数配置二、垃圾收集器配置三、GC策略配置3.1、基础通用配置3.2、Parallel 和 Parallel Old 常用参数配置3.3、CMS 常用参数配置3.4、G1 常用参数配置 四、GC日志配置五、dump 日志参数配置5.1、OutOfMemory异常时生成dump文件5.2、发生Full GC时生成dump文件…

QT安装与helloworld

文章目录 QT安装与helloworld1.概念&#xff1a;2.安装QT3.配置环境变量4.创建项目5.运行效果 QT安装与helloworld 1.概念&#xff1a; Qt Creator是一个用于Qt开发的轻量级跨平台集成开发环境。Qt Creator可带来两大关键益处&#xff1a;提供首个专为支持跨平台开发而设计的…

在Python中执行Linux Shell脚本详解

概要 随着 Python 的增长和普及,目前它已经成为自动化各种任务,包括执行 shell 脚本的主要工具。这篇文章将详细描述如何在 Python 中执行 shell 脚本,并提供丰富的示例帮助你理解和实践。 什么是Shell脚本? Shell脚本是一个由命令行解释器执行的文本文件。这些脚本包含控…

数据结构第九天(堆排序)

目录 前言 概述 源码&#xff1a; 主函数&#xff1a; 运行结果&#xff1a; 其他 前言 哈哈&#xff0c;这个堆排序算法很久之前就已经敲过一遍了&#xff0c;时间一久&#xff0c;思路有点淡忘。今天重新看过一遍之后&#xff0c;又亲自撸代码&#xff0c;幸运的是&am…

【MATLAB源码-第137期】基于matlab的NOMA系统和OFDMA系统对比仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 NOMA&#xff08;非正交多址&#xff09;和OFDMA&#xff08;正交频分多址&#xff09;是两种流行的无线通信技术&#xff0c;广泛应用于现代移动通信系统中&#xff0c;如4G、5G和未来的6G网络。它们的设计目标是提高频谱效…

如何使用C#调用LabVIEW算法

新建一个工程 这是必须的&#xff1b; 创建项目 项目 点击完成&#xff1b; 将项目另存为&#xff1b;方便后续的使用&#xff1b; 创建 一个测试VI 功能很简单&#xff0c;用的一个加法&#xff1b;将加数A&#xff0c;B设置为输入&#xff0c;和C设置为输出&#xff0c;…

正点原子--STM32通用定时器学习笔记(2)

1. 通用定时器输入捕获部分框图介绍 捕获/比较通道的输入部分&#xff08;通道1&#xff09; 输入通道映射CC1S[1:0]→采样频率CKD[1:0]→滤波方式IC1F[3:0]→边沿检测方式CC1P→捕获分频ICPS[1:0]→使能捕获CC1E 输入部分对相应的TIx输入信号采样&#xff0c;并产生一个滤波后…

MPLS——多协议标签交换

目录 1 多协议标签交换 MPLS 1.1 MPLS 的工作原理 1.1.1 MPLS 工作特点 1.1.2 MPLS 协议的基本原理 1.1.3 MPLS 的基本工作过程 1.2 转发等价类 FEC 1.2.1 FEC 用于负载平衡 1.3 MPLS 首部的位置与格式 1.3.1 MPLS 首部的位置 1.3.2 MPLS 首部的格式 1.4 新一代的…

STM32 HAL NTC(3950 10k)查表法

NTC&#xff08;Negative Temperature Coefficient&#xff09;是指随温度上升电阻呈指数关系减小、具有负温度系数的热敏电阻现象和材料。该材料是利用锰、铜、硅、钴、铁、镍、锌等两种或两种以上的金属氧化物进行充分混合、成型、烧结等工艺而成的半导体陶瓷&#xff0c;可制…