【C++】类和对象 - 下

news2024/9/23 23:30:58

目录

  • 1. 再谈构造函数
    • 1.1 构造函数体赋值
    • 1.2 初始化列表
    • 1.3 explicit关键字
  • 2. static成员
    • 2.1 概念
    • 2.2 特性
  • 3. 友元
    • 3.1 友元函数
    • 3.2 友元类
  • 4. 内部类
  • 5. 匿名对象
  • 6. 拷贝对象时的一些编译器优化

1. 再谈构造函数

1.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 初始化列表

实例化一个对象时,是给这个对象整体开辟一块空间,而其中的每个成员变量则是在初始化列表中进行初始化的,而非在构造函数体内

初始化列表的语法:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式:

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. 类中包含以下成员必须放在初始化列表位置进行初始化引用成员变量、const成员变量和自定义类型成员(且该类没有默认构造时)。

  3. 对于自定义类型成员变量,一定会先使用初始化列表初始化。

对于const和引用变量来说,const变量只有一次初始化的机会,就是在定义的时候,而引用变量也是要在定义的时候就要引用一个实体,因为函数体中进行的是赋值,并不是初始化,因此要在初始化列表中进行定义和初始化。

对于自定义类型,若没有能直接使用的默认构造,则也是必须通过初始化列表传递参数,这样编译器才能调用它的构造函数;若有默认构造,则不需要在初始化列表中显式地写。

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)
	{}
	A _aobj;      //A类中没有默认构造
	int& _ref;	  //引用
	const int _n; //const成员
};

对于这种类型,也需要使用初始化列表来初始化:

class C {
public:
	C(int a = 0) 
		:_a(a) 
	{ }
	int _a;
};
class D {
public:
	C _c;
};
int main() {
	D d0;
	return 0;
}

D类型中的成员变量是自定义类型C的对象,并且C类中已经实现了默认全缺省构造函数,因此D类中是可以不写默认构造的,不写编译器也会自动生成然后调用C的构造,但是每次构造后_c中的成员变量_a的值始终是缺省值0,那如果想通过给D类型对象传参来控制_c对象中_a变量的值时该怎么做?

同样只能通过初始化列表的方式,显式地传参调用C类中的默认缺省构造,因此D类中的构造函数要自己实现,并且要满足有一个默认构造:

class D {
public:
	//最好写成全缺省的构造
	//即默认构造
	D(int x = 0) 
		:_c(x) 
	{ }
	C _c;
};

这样就可以在调用的时候给D类对象传递参数来控制_c对象中_a的值:

int main() {
	D d0;
	//不传,_a为缺省值0
	D d1(1);
	//传了,_a就是你传递的值
	return 0;
}
  1. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,编译器都会先走一遍初始化列表

初始化列表能完成绝大多数的初始化工作,但始终有些还是无法完成,只能在函数体内部解决,所以若初始化列表不方便做的,就放在函数体中做

有了对初始化列表的理解,对于给成员变量声明缺省参数的做法,本质也是调用构造函数时把缺省值传递给初始化列表来对其进行初始化。

  1. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。
class A
{
public:
	A(int a)
		:_a1(a)
		, _a2(_a1)
	{}

	void Print() {
		cout << _a1 << " " << _a2 << endl;
	}
private:
	int _a2;
	int _a1;
};
int main() {
	A aa(1);
	aa.Print();
}

这里的输出结果是1和随机值,因为_a2先声明_a1后声明,因此先用_a1初始化_a2,但是_a1此时是随机值,然后在用传入的参数1来初始化_a1。

1.3 explicit关键字

class AA {
public:
	AA(int a) :_a(a) {
		cout << "AA(int a)" << endl;
	}
	AA(const AA& a) :_a(a._a) {
		cout << "AA(const AA& a)" << endl;
	}

private:
	int _a;
};

int main() {
	AA a1(1);
	AA a2 = 2;
	return 0;
}

对于以上两种实例化对象的方式,第一种很明显是构造。
第二种,因为2是整形,与AA类型不符合,因此会发生隐式类型转换,转换过程为:先用2去构造一个AA类型的临时对象,再用这个临时对象去拷贝构造a2,但是编译器会对这种在一个表达式中连续构造的情况进行优化,直接优化为用2来构造a2对象,以此提高效率。

在这里插入图片描述
如何证明编译器创建了一个临时对象?
在这里插入图片描述
可以发现如果引用这个临时对象,编译器会报错,因为临时对象具有常量属性,必须要用const修饰

对于内置类型也是同样的情况,这里也发生了隐式类型转换:
在这里插入图片描述
d并不是引用i,而是编译器用i初始化了一个double类型的临时对象,d是引用的这个临时对象,同样需要加上const来修饰。
在这里插入图片描述
如果不想让隐式类型转换的行为发生,就需要用到explicit关键字,用它来修饰构造函数,即禁止了构造发生隐式类型转换的情况
在这里插入图片描述

2. static成员

若想统计一个类实例化了多少对象(程序中现存的对象),该怎么做呢?

其中一种做法是使用全局变量,构造或拷贝构造就++,析构–:

int _scount = 0;
class AA {
public:
	AA() { ++_scount; }
	AA(const A & t) { ++_scount; }
	~AA() { --_scount; }
private:
	int _a;
};

这种方法可以解决问题,但因为它是全局变量,任何地方都可以修改它,所以若其它地方不小心修改了这个全局变量,那么结果就会出错。

2.1 概念

介于这种情况,C++设计出了静态成员变量,把该变量封装在了类中:

class AA {
public:
	AA() { ++_scount; }
	AA(const A & t) { ++_scount; }
	~AA() { --_scount; }
private:
	int _a;
	static int _scount;
};

什么是静态成员?
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。

与普通成员变量不同的是:
普通成员变量是属于不同的对象,即不同的对象存储着不同的成员变量;而静态成员变量是属于整个类的,单独存储在静态区,因此不属于任何一个对象,但是每个对象都可以共享使用它;初始化的方法也不同,静态成员变量一定要在类外进行初始化,不属于任何对象就不能在构造函数中初始化,只能在全局。

同样也无法声明缺省值,除非加上const,但是给了const就无法修改了

//类外
int AA::_scount = 0;

是类中的成员,需要在变量名前指定类域,同样只能初始化一次。

若要访问它,可以通过下面这种方式:

//指定访问类中的静态成员变量
int cnt = AA::_scount;

但如果_scountprivate修饰,外部也是没有办法访问到的,因此也需要使用公有的成员函数来访问:

class AA {
public:
	AA() { ++_scount; }
	AA(const A & t) { ++_scount; }
	~AA() { --_scount; }
	int GetAACount() { 
		return _scount; 
	}
private:
	int _a;
	static int _scount;
};

如果上面这种成员函数,则必须通过创建一个对象来调用,因为要传递this指针,若不想创建对象就调用这个成员函数,则要把其定义为静态成员函数

static int GetACount() { 
	return _scount; 
}

与普通成员函数的区别在于参数里没有this指针,又因为没有this指针,所以静态成员函数无法访问非静态成员变量

下面这段代码会报错:

static int GetACount() { 
	//无法访问非静态成员变量*_a
	_a = 0;
	return _scount; 
}

调用这个静态成员函数的方式除了通过对象来调用的方式之外还多了一种:类名::函数名()

//直接指定类域调用
int cnt = AA::GetACount();

//创建对象调用也是可以的
AA a;
int cnt = a.GetACount();

因此当类中有静态成员变量时大多数情况下都要为其配备一个静态成员函数。

静态成员变量具有全局性,只不过受访问限定符的约束

【问题】

  1. 非静态成员函数可以调用类的静态成员函数吗?
  2. 静态成员函数可以调用非静态成员函数吗?

有了上面的理解就很好回答了,非静态成员函数中访问对象中的成员变量或者调用其它成员函数都是通过this指针来操作的,即使是静态成员也可以通过this指针访问,所以非静态成员函数可以调用类的静态成员函数。
而静态成员函数并没有传递this指针,因此是没有办法访问非静态成员的。

如何设计一个类,使得在类外只能在栈上创建对象?

class AA {
public:
	static AA getStackObj() {
		AA aa;
		return aa;
	}
private:
	AA() {}
	int _a = 0;
};
int main() {
	AA a = AA::getStackObj();
	return 0;
}

将构造函数私有化,外面无法直接调用,但类中不受限制,然后在类中定义一个公有的成员函数,创建一个栈上的对象将其返回,但是该函数必须要是静态成员函数,这样不需要对象即可调用,否则得先创建对象,但是构造函数被私有化了,创建不了,那这个函数就也无法调用了,所以要定义为静态成员函数。

只能在堆上创建对象也是同理

2.2 特性

简单总结下静态成员的特性:

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问。
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制。

3. 友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

耦合度是指两者之间的关联程度

友元分为:友元函数和友元类

3.1 友元函数

上篇文章简单介绍过重载operator<<,使其能输出自定义类型,然后发现没办法将operator<<重载成成员函数。
因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。可是this指针默认是第一个参数也就是左操作数了。
但实际使用中cout需要是第一个形参对象,才能正常使用。所以要将operator<<重载成全局函数。
但又会导致类外没办法访问成员,此时就需要友元来解决,operator>>同理。

class Date
{
	friend ostream& operator<<(ostream& _cout, const Date& d);
	friend istream& operator>>(istream& _cin, Date& d);
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year), _month(month), _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << "-" << d._month << "-" << d._day;
	return _cout;
}
istream& operator>>(istream& _cin, Date& d)
{
	_cin >> d._year >> d._month >> d._day;
	return _cin;
}
int main()
{
	Date d;
	cin >> d;
	cout << d << endl;
	return 0;
}

关于友元函数:

  1. 友元函数可访问类的私有和保护成员,但不是类的成员函数
  2. 友元函数不能用const修饰。
  3. 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
  4. 一个函数可以是多个类的友元函数。
  5. 友元函数的调用与普通函数的调用原理相同。

3.2 友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的私有成员。

class Time
{
	// 声明日期类为时间类的友元类
	//则在日期类中就直接访问Time类中的私有成员变量
	friend class Date;   
	//Data类中的所有成员函数都是Time类的友元函数
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		: _hour(hour), _minute(minute), _second(second)
	{}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year), _month(month), _day(day)
	{}
	void SetTimeOfDate(int hour, int minute, int second)
	{
		// 直接访问时间类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

关于友元类:

  1. 友元关系是单向的,不具有交换性。

比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。

  1. 友元关系不能传递

如果C是B的友元, B是A的友元,则不能说明C时A的友元。

  1. 友元关系不能继承,后续会介绍。

4. 内部类

概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类

class A {
private:
	static int k;
	int h;
	void print() const {
		cout << h;
	}
public:
	class B {
	public:
		void foo(const A& a) {
			cout << k << endl;//OK?
			cout << a.h << endl;//OK?
			a.print();//OK?
		}
	};
};
int A::k = 1;

A类的大小是4字节,k是静态成员变量,不存储在对象中,B类只是在A类中声明,并没有占空间,只有用B创建对象才会占空间,所以实际A类对象中只有变量h占了4个字节。

内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。

实例化一个A类对象,并不会实例化B类的对象,除非A类中有B类的对象

若想创建B类对象,必须要先指定它在哪个类域中:

int main() {
	//指定类域
	A::B b;
	return 0;
}

内部类受访问限定符的限制,若是私有,则外部无法直接找到B类

注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。

由于内部类天生就是外部类的友元,因此B类中的foo函数想输出A类中的私有成员变量以及调用A类中的成员函数是OK的

特性:

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名
  3. sizeof(外部类)=外部类,和内部类没有任何关系。

5. 匿名对象

class A
{
public:
	A(int a = 0) :_a(a) {
		cout << "A(int a)" << endl;
	}
	 ~A()  {
		 cout << "~A()" << endl;
	 }
private:
	int _a;
};

定义匿名对象:

int main()
{
	//有名对象
	A aa1(1);
	//匿名对象
	A(2);
	return 0;
}

有名对象和匿名对象的区别:

有名对象的生命周期在它当前被定义的局部域中,而匿名对象的是生命周期只有被定义的那一行

匿名对象的用途之一在于,只想单纯地调用该类中的成员函数,比如以下类:

class Solution {
public:	
	int Sum_Solution(int n) {
		//...
		return n;
	}
};

则可以使用匿名对象来调用:

int main()
{
	int ret = Solution().Sum_Solution(10);
	return 0;
}

这种情况下用匿名对象比较方便。

能否引用一个匿名对象?

int main()
{
	const A& a = A();
	return 0;
}

可以,但必须用const修饰,匿名对象与临时对象相似,都具有常量属性,因此要加上const,除此之外,被引用的匿名对象的生命周期被延长了,延长到它当前被定义的局部域中。

6. 拷贝对象时的一些编译器优化

对于以下代码:

A func() {
	A aa;
	return aa;
}
int main()
{
	A ret = func();
	return 0;
}

一般而言,调用这个函数返回时会发生两次拷贝构造,传值返回要拷贝构造一个临时对象,返回的是这个临时对象,然后再用返回的这个临时对象拷贝构造ret。

比较老的编译器是这种情况,而最新的编译器都会对其进行优化,对于同一行的表达式如果有构造+拷贝构造或者连续拷贝构造会直接优化为拷贝构造。

只有同一个表达式中这种类似于连续构造或者拷贝构造的情况才会触发编译器的优化,不同的表达式中不会发生

在这里插入图片描述
因此能写在一行就尽量写在一行,不仅方便,编译器还会对其进行优化。
在这里插入图片描述
可以发现二者的区别,第一种写法比第二种写法直接优化了一个构造和一个赋值重载,优化是比较大的。

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

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

相关文章

【供电并接电路】2021-12-31

缘由在实际应用中mos管的导通问题 - 电路设计论坛 - 电子技术论坛 - 广受欢迎的专业电子论坛!MOS管实际应用中的开通问题-硬件开发-CSDN问答 设计的思想是&#xff0c;当CH_5.2V有5.2V电压时&#xff0c;Q7导通&#xff0c;Q6产生UGS​压差&#xff0c;从而使Q6导通&#xff0c…

在校外连接校内实验室服务器

zerotier 内网穿透 一、zerotier的操作 去官网注册、登录、创建网络 zerotier官网 我使用微软账号登录的&#xff0c;这个随便 点 Create A Network NETWORK ID点ID进去 二、服务器(校内)上的操作 1. Ubuntu配置SSH 如果出现不在sudoers列表的问题查看这里 sudo apt …

element-ui树形表格,左边勾选,右边显示选中的数据-功能(如动图)

功能如图 功能需求 表格树形表格勾选数据&#xff0c;右边显示对应勾选的数据内容&#xff0c;选中客户&#xff0c;自动勾选所有的店铺(子级)&#xff0c;选中其中一个店铺&#xff0c;自动勾选上客户(父级)&#xff0c;同时会存在只有客户&#xff08;下面没有子级的情况&am…

Unity Image(RawImage) 实现按轴心放大缩小,序列化存储轴心信息,实现编译器窗口保存轴心

工作时分配给我的要实现的功能&#xff0c;写的时候遇到挺多的坑的&#xff0c;在此记录一下 效果 放大缩小的效果 2.编译器扩展窗口记录 实现点 1.Json序列化存储图片轴心位置, 放大倍率&#xff0c;放大所需要的事件 2.用了编译器扩展工具便于保存轴心信息坑点 1.Imag…

【Linux】多路转接 -- select函数

文章目录 1. 认识select函数2. select函数原型3. socket就绪条件4. select工作流程5. select服务器6. select的优缺点 首先我们要了解一下&#xff0c;什么是多路转接&#xff1f; 多路转接也叫多路复用&#xff0c;是一种用于管理多个IO通道的技术。它能实现同时监听和处理多个…

C++ 访问控制——公有继承、私有继承、保护继承

派生类继承了基类的全部数据成员和除了构造函数和析构函数之外的全部函数成员&#xff0c;但是这些成员的访问属性在派生的过程中是可以调整的。从基类继承的成员&#xff0c;其访问属性由继承方式控制。 基类的成员有public&#xff08;公有&#xff09;、protected&#xff…

ArduPilot开源代码之Companion Computers简单分析

ArduPilot开源代码之Companion Computers简单分析 1. 源由2. 伴机系统2.1 APSync2.2 DroneKit2.3 FlytOS2.4 Maverick2.5 ROS2.6 Rpanion-server 3. 总结4. 参考资料 1. 源由 从稳定性&#xff0c;社区群体&#xff0c;以及开源方式的角度看&#xff0c;Ardupilot是不错的选择…

骑砍二 ATC MOD 使用教程与应用案例解析

骑砍二 ATC MOD 使用教程与应用案例解析 作者&#xff1a;blibli-财不外漏 / NEXUSMODS-PuepleKarmen 案例MOD依赖&#xff1a;ATC - Adonnay’s Troop Changer & AEW - Adonnay’s Exotic Weaponry & New Armor 文本编辑工具&#xff1a;VS Code&#xff08;推荐使用&…

【小沐学NLP】在线AI绘画网站(百度:文心一格)

文章目录 1、简介2、文心一格2.1 功能简介2.2 操作步骤2.3 使用费用2.4 若干示例2.4.1 女孩2.4.2 昙花2.4.3 山水画2.4.4 夜晚2.4.5 古诗2.4.6 二次元2.4.7 帅哥 结语 1、简介 当下&#xff0c;越来越多AI领域前沿技术争相落地&#xff0c;逐步释放出极大的产业价值&#xff0…

Amazon CloudFront 部署小指南(四)- CloudFront Function 基础与诊断

内容简介 本文适用于希望使用 Amazon CloudFront Functions 提升 Amazon CloudFront 边缘计算能力的用户&#xff0c;旨在帮助您更好的进行 CloudFront Functions 的开发、调试、测试、部署等工作。 首先我们会对 CloudFront Function 做个简单的介绍&#xff0c;然后分为七个步…

全志F1C200S嵌入式驱动开发(应用程序开发)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 我们在开发soc驱动的时候,很多情况下也要验证下当前的驱动功能是否正确。当然除了验证驱动功能之外,我们还要编写业务代码和流程代码。这中间就和各行各业有关了,有的是算法,有…

Redis BigKey案例

面试题&#xff1a; 阿里广告平台&#xff0c;海量数据里查询某一固定前缀的key小红书&#xff0c;你如何生产上限制keys*/flushdb/flushall等危险命令以防止误删误用&#xff1f;美团&#xff0c;MEMORY USAGE命令你用过吗&#xff1f;BigKey问题&#xff0c;多大算big&#…

GODOT游戏引擎简介,包含与unity性能对比测试,以及选型建议

GODOT&#xff0c;是一个免费开源的3D引擎。本文以unity作对比&#xff0c;简述两者区别和选型建议。由于是很久以前写的ppt&#xff0c;技术原因视频和部分章节丢失了。建议当做业务参考。 GODOT目前为止遇到3个比较重大的基于&#xff0c;第一个是oprea的合作奖&#xff0c;…

【redis】redis的认识和安装

目录 1.redis是什么2.Redis的特点3.安装redis4.设置远程连接4.1 开启隧道4.2 可视化客户端连接4.3 开启防火墙 5.redis常见数据类型5.1 redis的一些全局命令5.2 数据结构 6. redis的典型应用---缓存&#xff08;cache&#xff09;6.1 使用redis做缓存6.2 缓存穿透&#xff0c;缓…

【绪论0】

#pic_center R 1 R_1 R1​ R 2 R^2 R2 目录 知识框架No.0 引言No.1 操作系统的概念功能和定义一、操作系统的概念和定义1、电脑的演变 二、操作系统的功能和目标 No.2 操作系统的特征一、并发二、共享三、虚拟四、异步 No.3 操作系统的发展与分类一、手工操作阶段二、批处理阶段…

Windows11 家庭中文版关于本地组策略编辑器gpedit.msc找不到即打不开的解决办法(征诚小张售后实测有效)

Windows11 家庭中文版关于本地组策略编辑器gpedit.msc找不到即打不开的解决办法 根本原因&#xff1a;是因为Windows11家庭中文版的 版本系统没内置安装本地策略组编辑器 好了废话不多说 直接说解决办法 第一步 首先电脑上新建一个空文本文件 输入以下内容&#xff1a; echo o…

Android Studio安装AI编程助手Github Copilot

csdn原创谢绝转载 简介 文档链接 https://docs.github.com/en/copilot/getting-started-with-github-copilot 它是个很牛B的编程辅助工具&#xff0c;装它&#xff0c;快装它&#xff0e; 支持以下IDE: IntelliJ IDEA (Ultimate, Community, Educational)Android StudioAppC…

Qt应用开发(基础篇)——时间类 QDateTime、QDate、QTime

一、前言 时间类QDateTime、QDate、QTime、QTimeZone保存了Qt的时间、日期、时区信息&#xff0c;常用的时间类部件都会用到这些数据结构&#xff0c;常用概念有年、月、日、时、分、秒、毫秒和时区&#xff0c;时间和时区就关系到时间戳和UTC的概念。 UTC时间&#xff0c;又称…

FPGA初步学习之串口发送模块【单字节和字符串的发送】

串口相关简介 UART 在发送或接收过程中的一帧数据由4部分组成&#xff0c;起始位、数据位、奇偶校验位和停止位&#xff0c;如图所示。其中&#xff0c;起始位标志着一帧数据的开始&#xff0c;停止位标志着一帧数据的结束&#xff0c;数据位是一帧数据中的有效数据。 通常用…

【贪心算法】leetcode刷题

贪心算法无固定套路。 核心思想&#xff1a;先找局部最优&#xff0c;再扩展到全局最优。 455.分发饼干 两种思路&#xff1a; 1、从大到小。局部最优就是大饼干喂给胃口大的&#xff0c;充分利用饼干尺寸喂饱一个&#xff0c;全局最优就是喂饱尽可能多的小孩。先遍历的胃口&a…