c++终极螺旋丸:₍˄·͈༝·͈˄*₎◞ ̑̑“类与对象的结束“是结束也是开始

news2024/10/1 12:27:15

 

 

文章目录

  • 前言
  • 一.构造函数中的初始化列表
  •      拷贝对象时的一些编译器优化
  • 二.static成员
  • 三.友元
  • 四.内部类
  • 总结

 


前言

前两期我们将类和对象的重点讲的差不多了,这一篇文章主要进行收尾工作将类和对象其他的知识点拉出来梳理一遍,并且补充前两篇没有讲过的小细节。


 

一、构造函数中的初始化列表

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

aa8eb8b90b164db7b236d653c883dd05.png

bb54c926796948d79ae9762a75857694.png 为什么加入了一个const变量就无法引用默认的构造函数了呢?

我们都知道,const成员在定义的时候必须初始化,前面我们介绍过可以加缺省值,但是缺省值也不是初始化,那么到底在哪初始化呢?这就要介绍到构造函数的初始化列表了,初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个成员变量后面跟一个放在括号中的初始值或表达式。

class A
{
public:
	//1.哪个对象调用初始化函数,初始化列表是它所有成员变量初始化的地方
	//2.不管是否显示在初始化列表写,编译器会让每个变量都在初始化列表定义初始化
	A()
		:_x(1)
		,_a2(1)
	{
		_a1++;
		_a2--;
	}
private:
	int _a1 = 1;   //声明  使用缺省值并不是初始化
	int _a2 = 2;
	const int _x ;
};
int main()
{
	A aa;   //对象整体的定义,每个成员什么时候定义呢?
	return 0;
}

 那么大家可以猜一猜a1和a2的值分别是多少呢?当我们给初始化的时候就不用缺省值了,所以在初始化列表中a2被初始化为1,而a1没有初始化所以用了缺省值1,a1++后变成了2,a2--后变成了0,所以答案是2和0.

4ffb22d02adc4e05a8d16a49ebb89894.png

 初始化列表中,const修饰的变量,引用类型和自定义类型(没有默认构造的自定义类型)都必须在初始化列表初始化,不然编译器会报错,并且自定义类型初始化回去调用其自定义类型的构造函数。

class B
{
public:
	B()
		:_b(1)
	{
		cout << "B()" << endl;
	}
private:
	int _b;
};
class A
{
public:
	//1.哪个对象调用初始化函数,初始化列表是它所有成员变量初始化的地方
	//2.不管是否显示在初始化列表写,编译器会让每个变量都在初始化列表定义初始化
	A()
		:_x(1)
		,_a2(1)
		,ret(_a1)
		,_bb()
	{
		_a1++;
		_a2--;
	}
private:
	int _a1 = 1;   //声明  使用缺省值并不是初始化
	int _a2 = 2;
	//有三类变量必须在初始化列表初始化
	const int _x ;
	int& ret;
	B _bb;
};

a184a278e2e1426b8860c09b4bfcc4ae.png

 那么如果自定义类型是带参的构造函数我们该如何初始化呢?

1bdac728689b4513b8019de62f676206.png

这种带参的我们只需要在括号内传个值即可,编译器会去调用它的构造函数初始化。

注意:初始化列表中每个成员只能出现一次,因为初始化只能一次不能初始化两次。

建议:尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。

下面我们看一道题:

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

上面这道题答案应该是什么呢?首先我们定义了对象A并且调用构造函数传了1过去,这时候大多数人会认为a1先被初始化为1,然后s2被a1初始化也是1,但其实结果并不是这样。有这样一条规则:成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后顺序无关。也就是说初始化的顺序是看谁先声明的,谁先声明谁就先初始化,所以在上面那道题中a2先声明所以a2先用a1初始化,而这个时候的a1是随机数,所以a2被初始化为随机数,然后a1进行初始化,a1用a初始化所以a1是1,那么答案就是1和随机值。

ebaa226185ec40149c7fff0e98241e75.png

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

下面我们讲一下编译器的优化:

构造函数不仅可以构造与初始化对象, 对于单个参数或者除第一个参数无默认值其余均有默认值
的构造函数,还具有类型转换的作用
class A
{
public:
	A(int a)
		:_a1(a)
	{}
private:
	int _a2;
	int _a1;
};
int main() {
	A aa(1);
	A aa2 = 1;
}

 为什么我们能直接用1去初始化aa2呢?要知道1是整形,而aa2是自定义类型,其实这里包含了编译器优化,首先我们要知道这里是隐式类型转换,就像下图:

15913bf35a8b44d886add47f6b981237.png

在这里是直接把i给d吗?其实不是,这里会先开一个double的临时变量,并且临时变量具有常性,先将i给这个double类型的临时变量,然后再将这个临时变量给d。

而自定义类型也一样,其实是先将1给A类型的临时变量,这个临时变量会调用构造函数用1初始化,然后用拷贝构造函数将临时变量给aa2。这样说来我们应该是调用了构造+拷贝构造我们验证一下:

如何确定确实有一个临时变量呢?

26cca8a9c8774649b41d7a0c8cf994ac.png

 我们通过传引用发现会报错初始值必须为不可修改的左值,然后我们加个const试一下:

8edde96b7e164e39a61bab6209e4b66b.png

我们之前说过临时变量具有常性必须加const,在这里我们普通变量会报错而加了const就能正常这就说明了在类型转换期间一定是有临时变量的。 

class A
{
public:
	A(int a)
		:_a1(a)
	{
		cout << "A(int a)" << endl;
	}
	A(const A& d)
	{
		cout << "A(const A& d)" << endl;
		_a2 = d._a2;
		_a1 = d._a1;
	}

private:
	int _a2;
	int _a1;
};
int main() {
	//A aa(1);
	A aa2 = 1;
	
}

 bff420eeea18408c8640a6396f1e88f0.png

这里为什么只调用了一个构造函数呢?其实这里就是编译器的优化了, 编译器直接优化为用1去构造aa2。也就是说实际过程变成了:构造+拷贝构造+编译器优化-->构造。那如果我们不想让编译器优化有什么办法呢?这里c++引入了explicit关键字,将关键字加到构造函数前面编译器就不能进行类型转换了。如下图:

9161781cb77e4a409afd727a6ea44b40.png

 968b56d5b318422ca07b1facfa9cf149.png

上面是单参数的构造函数,那如果是多参数的构造函数呢?

61bd107c81984221825fadc53efd9695.png 1635f168a76140a18a548a397107b6f5.png

  如上图所示, 多参数的构造函数也支持只不过需要加大括号,在这里要说明一下,单参数的隐式类型转换是c++98就支持的,而多参数的隐式类型转换是c++11支持的。同样我们在前面加一个explicit就不支持了。

同样编译器还会对函数传参进行优化:

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}
	A(const A& aa)
		:_a(aa._a)
	{
		cout << "A(const A& aa)" << endl;
	}
	A& operator=(const A& aa)
	{
		cout << "A& operator=(const A& aa)" << endl;
		if (this != &aa)
		{
			_a = aa._a;
		}
		return *this;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
void func1(A aa)
{}

int main()
{
	A aa1;
	func1(aa1);  //
	func1(2);   //构造 + 拷贝构造 + 优化 -> 构造
	func1(A(3));  //构造 + 拷贝构造 + 优化 ->构造
	return 0;
}

通过调试我们发现,func1(2)本来应该是构造+拷贝构造,结果被优化成了构造。func(A(3))也一样,A(3)是一个匿名对象,然后将A(3)拷贝给aa,然后优化为构造。

 那么如果函数参数变成传引用还会优化吗?

79376916dcb64927a953e1f0c85963f6.png

808bf4be87614407a7fbf8478e2358f3.png 首先Func2的参数前面必须const,否则连编译都不会通过,因为Func2(2)中2是一个常量。其次我们可以看到当传引用的时候编译器是不会优化的,因为传引用本身就是将自身传过去,没有什么再减少空间开辟的优化了。再看下一个:

ea20870986fc428aa9272ddd10de6af2.png

这里func3的顺序大家应该都清楚,进入函数后aa先构造,然后值返回会调用拷贝构造,函数要结束时aa调用析构,那么A aa1 = func3()的过程是什么样呢?这个过程按照我们所学的知识来理解应该是构造,拷贝构造,然后再拷贝构造赋值给aa1所以应该是1个构造2个拷贝构造。那么我们验证一下:

963efc6fd59a41d49b5cb91e0b917e23.png 我们发现只有1个构造1个拷贝构造,其实这里是被编译器优化了。

c35b2933ca154d7194716caa756db319.png

 当我们直接返回匿名对象的时候发现本来应该构造+拷贝构造直接变成了构造。再看下图:

22562a5b3be5453d945738ba33c5f316.png

这个我们发现更神奇了,本来应该是构造+拷贝构造+拷贝构造直接被优化为1个构造,编译器直接用匿名对象初始化aa1了。所以我们得出一个结论:能用匿名对象直接返回的就用匿名对象这样会加速编译器的优化。 

编译器优化总结:

1.对象返回

接收返回值对象,尽量拷贝构造方式接收,不要赋值接收。

函数中返回对象时,尽量返回匿名对象。

2.函数传参总结

尽量使用const & 传参

二、static成员

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量,用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。

我们先用以前的知识实现一个类,这个类可以计算出创建了多少个对象。

int count = 0;
class Test
{
public:
	Test()
	{
		count++;
	}
};
int main()
{
	Test t1;
	cout << count << endl;
	return 0;
}

 按照我们以前的写法我们发现是无法正常编译的,我们看一下报错信息:

f4788200bac542bfa11c5cb92c7260b9.png

这是因为我们定义的全局变量的名称与库中的某个函数名冲突了,如果是以前我们直接修改变量名称即可,但我们既然学了c++就用c++的方式解决,我们知道c++的类中定义的变量名称是不会与库中的名称冲突的,那我们如何既能将变量写到类中又能让这个变量不属于这个单独的类属于所有的类对象呢?这里就用到了static修饰的变量。如下图:

class Test
{
public:
	Test()
	{
		count++;
	}
	static int count;
};
int Test::count = 0;
int main()
{
	Test t1;
	cout << t1.count << endl;
	return 0;
}

static修饰的变量或函数不属于某个对象,属于所有对象,属于整个类。静态成员变量必须在类外进行初始化,类中仅仅是声明。 

 我们再多加几个变量2bcca8fd47904381b23caadf1fc4a7fa.png

 这样还不算成功的计算出所有创建对象的数量,看下图:

77e56c334c81484785f7a4711822cb92.png

当我们调用拷贝构造创建一个新的对象的时候发现数量不对了,我们应该要加上拷贝出来的对象的数量,所以我们改进一下:

e53baaa7c90c43d5b8a25bd534fb6eda.png

 这样即使我们利用拷贝构造创建新对象也会成功加上数量。

那如果定义的count是私有的该怎么办呢?

1b535a636be34c00a7be49704540f41a.png

私有的很明显是不能直接访问的,所以我们利用函数去返回。

1575088aafb944aaaef362434fd07f8c.png

381ce71b72994b45a523b70e42576b32.png 但是如果我们没有创建对象呢?我们不能因为调用一个函数再去创建一个类对象吧,这时候就该静态函数出场了。

class Test
{
public:
	Test()
	{
		count++;
	}
	Test(const Test& d)
	{
		count++;
	}
	static int GetCount()
	{
		return count;
	}
private:
	static int count;
};
int Test::count = 0;
int main()
{
	cout << Test::GetCount() << endl;
	return 0;
}

f8b2892dab234949aa27c73405ef7a07.png

 静态函数可以直接用类名访问,并且静态函数内不可以访问普通成员变量。如下图:

da07896995914c27a3dbc1a5130437e9.png

静态成员特性:

1.静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。

2.静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。

3.类静态成员即可用类名::静态成员或者对象.静态成员来访问。

4.静态成员函数没有隐藏的this指针,不能访问任何非静态成员.

5.静态成员也是类的成员,受public,protected, private访问限定符的限制。

6f19005a75994fa8b17b08750d72feff.png

c3ac03b472e44fa18be3cca6ae256914.png 匿名对象到下一行直接就调用析构函数了所以声明周期只在这一行。

那么匿名对象有什么作用呢?

393a30bf4f6f44a088783644fed37cbf.png

比如我们需要一个值用来初始化一个对象,然后利用函数返回一个初始化的匿名对象即可。

三丶友元

友元其实我们之前已经接触过了,在运算符重载的时候我们需要重载<<符号用到了友元,友元提供了一种突破封装的方式,有时提供了便利。但是友元增加了耦合度,会破坏封装,所以友元不宜多用。

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

这是我们之前的例子:

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;
 _cin >> d._month;
 _cin >> d._day;
 return _cin;
}
int main()
{
 Date d;
 cin >> d;
 cout << d << endl;
 return 0;
}

说明:

1.友元函数可访问类的私有和保护成员,但不是类的成员函数。

2.友元函数不能用const修饰。

3.友元函数可以在类定义的任何地方声明,不受类访问限定符的限制。

4.一个函数可以是多个类的友元函数。

5.友元函数的调用和普通函数的调用原理相同 

友元类:

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
class Time
{
   friend class Date;   // 声明日期类为时间类的友元类,则在日期类中就直接访问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;
};

如上图所示,当我们创建了一个Date类的时候然后Date类中有私有自定义变量的时候,我们需要对这个自定义变量访问,这个时候就可以在time类中将Date类设为友元,Date类中就可以访问time类中的私有成员。但是友元关系是不可逆的,也就是说Time是不可以使用Date的变量的。

注意:

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

2.友元关系不能传递,如果C是B的友元,B是A的友元,不能说明C是A的友元。

3.友元关系不能继承

四丶内部类

概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员,外部类对内部类没有任何优越的访问权限。

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

特性:

内部类可以定义在外部类的public,protected,private都是可以的。

注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名

sizeof(外部类)=内部类,和内部类没有任何关系

14d15566351e4bf59284668b67a531b1.png

 通过上图我们可以发现,A类的大小是4字节也就是int h的大小,如果包含类B的大小应该是8字节才对,所以sizeof(外部类)与内部类无关。

受类域限制是什么意思呢?看下图:

e296d7f13a2345f682a5b903bba95a0a.png

B对象是无法直接定义的,需要加上域作用限定符。

5bfd3111915d4e36894e4f4a4ca8c1a5.png 当然这是类B公有的情况,如果类B是私有呢?

7c2e4f31b19b4f82b8d4c970283b0860.png

我们发现当类B是私有的时候是无法直接用类B创建对象的,这就证明内部类受外部类的类域限制。

class A
{
private:
	int h;
	int k;
public:
	class B
	{
	public:
		void Print(A& a)
		{
			cout << a.h << endl;
			a.k = 10;
		}
	private:
		int b;
	};
};
int main()
{
	A aa;
	A::B bb;
	return 0;
}

b56518acd9884dedb1430508ca9ad64e.png

 从上图可以发现内部类是外部类的友元类,我们在内部类B中直接访问了A类中的h和k变量。


总结

现实生活中的实体计算机并不认识,计算机只认识二进制格式的数据。如果想要让计算机认识现
实生活中的实体,用户必须通过某种面向对象的语言,对实体进行描述,然后通过编写程序,创
建对象后计算机才可以认识。比如想要让计算机认识洗衣机,就需要:
1. 用户先要对现实中洗衣机实体进行抽象---即在人为思想层面对洗衣机进行认识,洗衣机有什
么属性,有那些功能,即对洗衣机进行抽象认知的一个过程
2. 经过1之后,在人的头脑中已经对洗衣机有了一个清醒的认识,只不过此时计算机还不清
楚,想要让计算机识别人想象中的洗衣机,就需要人通过某种面相对象的语言(比如:C++、
Java、Python等)将洗衣机用类来进行描述,并输入到计算机中
3. 经过2之后,在计算机中就有了一个洗衣机类,但是洗衣机类只是站在计算机的角度对洗衣
机对象进行描述的,通过洗衣机类,可以实例化出一个个具体的洗衣机对象,此时计算机才
能洗衣机是什么东西。
4. 用户就可以借助计算机中洗衣机对象,来模拟现实中的洗衣机实体了。
在类和对象阶段,大家一定要体会到, 类是对某一类实体 ( 对象 ) 来进行描述的,描述该对象具有那
些属性,那些方法,描述完成后就形成了一种新的自定义类型,才用该自定义类型就可以实例化
具体的对象

 

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

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

相关文章

第3集丨Java中的异常、处理方式及自定义异常汇总

目录一、异常的分类1.1 常见的运行时异常1.2 常见的检查异常1.3 继承关系二、异常处理机制三、try…catch…finally四、声明抛出异常五、人工抛出异常六、自定义异常任何一种程序设计语言设计的程序在运行时都有可能出现错误&#xff0c;例如除数为0&#xff0c;数组下标越界&a…

别学英语了,真的

文 / 王不留&#xff08;微信公众号&#xff1a;王不留&#xff09; 这两年&#xff0c;很多朋友加我微信后&#xff0c;第一句常是&#xff0c;学英语有什么用啊&#xff1f; 我会统一给出真诚答复&#xff1a;没用&#xff0c;真的。 看新闻&#xff0c;中文海量信息已经严重…

建筑行业固定资产管理解决方案

建筑行业的固定资产种类和数量都较多&#xff0c;常用的固定资产有&#xff1a;办公设备、机械、设备、工具等。设备的调拨、购置、测试、验收、建帐立卡、分类编号、技术档案、供应分配、清查盘点、提取折旧、报废、设备维修、设备保养、备件管理、设备巡检和点检等工作&#…

S7-1200对于不同项目下的PLC之间进行开放式以太网通信的具体方法示例

S7-1200对于不同项目下的PLC之间进行开放式以太网通信的具体方法示例 如下图所示,打开TIA博途创建一个新项目,并通过“添加新设备”组态 S7-1200 客户端 ,选择 CPU1214C DC/DC/DC (client IP:192.168.0.102),建立新子网; 首先编写客户端程序:打开OB1编程界面,选择指令…

图片如何提取文字?

在当今信息爆炸的时代&#xff0c;图文并茂已经成为了一个广告宣传的常用方式。然而&#xff0c;图片中的文字信息往往难以获取&#xff0c;尤其对于那些需要快速获取信息的人们来说&#xff0c;阅读图片中的文字会是一项繁琐且费时的任务。现在&#xff0c;我们有一个好消息要…

如何熟练掌握Python在气象水文中的数据处理及绘图【免费教程】

pythonPython由荷兰数学和计算机科学研究学会的吉多范罗苏姆于1990年代初设计&#xff0c;作为一门叫做ABC语言的替代品。Python提供了高效的高级数据结构&#xff0c;还能简单有效地面向对象编程。Python语法和动态类型&#xff0c;以及解释型语言的本质&#xff0c;使它成为多…

[python课程设计1]学生成绩管理系统

引言本课程设计使用数据库&#xff0c;熟悉了Python语言操作数据库&#xff0c;对数据库的增删改查&#xff0c;实现Qt designer界面设计以及excel表格的读写&#xff0c;代码通俗易懂&#xff0c;方便对所学知识的掌握。需求分析用类对学生成绩、代码封装使得操作使用简单&…

java开启线程的四种方法

文章目录1、继承Thread类1.1 代码实现1.2 测试结果2、实现Runnable接口2.1 方式一&#xff1a;直接实现Runnable接口2.1.1 代码实现2.1.2 测试结果2.2 方式二&#xff1a;匿名内部类2.2.1 代码实现2.2.2 测试结果3、实现Callable接口3.1 代码实现3.2 测试结果4、创建线程池4.1 …

常见帧率计算方法实际效果对比及EasyCVR平台的帧率计算方法

什么是帧、帧数、帧率&#xff1f; 帧 &#xff08;Frame&#xff09; 帧可以理解为视频或者动画中的每一张画面&#xff0c;而视频和动画特效是由无数张画面组合而成&#xff0c;每一张画面都是一帧。 帧数&#xff08;Frames&#xff09; 帧数是帧生成的数量。如果一个动画…

Scala 变量和数据类型(第二章)

第二章、变量和数据类型2.1 注释2.2 变量和常量&#xff08;重点&#xff09;2.3 标识符的命名规范2.4 字符串输出2.5 键盘输入2.6 数据类型&#xff08;重点&#xff09;回顾&#xff1a;Java数据类型Scala数据类型2.7 整数类型&#xff08;Byte、Short、Int、Long&#xff09…

OpenAI CEO喊麦ChatGPT:你很酷,但却是个“糟糕的产品”

OpenAI 联合创始人兼CEO山姆阿尔特曼&#xff08;Sam Altman&#xff09;最近在一档播客节目中称ChatGPT 为“糟糕的产品”。 阿尔特曼说&#xff0c;“人们访问的是一个有时能用&#xff0c;有时不能用的网站。”他指的是ChatGPT频繁出现的错误消息。 他补充说道&#xff1a;…

【GO】K8s 管理系统项目[API部分--Workflow]

K8s 管理系统项目[API部分–Workflow] 年终于算过完了,身体也康复了,继续学习 1. DB设置 1.1 连接配置 service/config.go package configimport "time"const (ListenAddr "0.0.0.0:9091"KubeConfig "D:\\golang\\k8s-plantform\\config\\cka&…

有序表(中):Size Balanced Tree(SBT/SB树)

1、SB树简介 本质上是一棵二叉搜索树&#xff0c;SB树全称 Size Balanced Tree&#xff0c;顾名思义&#xff0c;这是一棵通过大小&#xff08;Size&#xff09;域来维持平衡的二叉搜索树。 它不仅支持简单的二叉搜索树操作&#xff0c;也支持 Select 和 Rank。 定义一下Siz…

每天一道大厂SQL题【Day10】电商分组TopK实战

每天一道大厂SQL题【Day10】电商分组TopK实战 大家好&#xff0c;我是Maynor。相信大家和我一样&#xff0c;都有一个大厂梦&#xff0c;作为一名资深大数据选手&#xff0c;深知SQL重要性&#xff0c;接下来我准备用100天时间&#xff0c;基于大数据岗面试中的经典SQL题&…

Linux入门篇(二)

Linux前言链接文件符号链接&#xff08;软链接&#xff09;硬链接shellshell 的类型shell的父子关系理解外部命令和内建命令外部命令内建命令Linux环境变量PATH环境变量前言 在这一章&#xff0c;我对Linux中有关shell较为深入的理解和环境变量方面知识的一个记录。同时&#x…

PBR工作流实现与对比

工作流实现工作流中的核心内容便是贴图&#xff0c;不论是UE4还是Unity都支持将PBR的参数以贴图的形式传入引擎&#xff0c;我们可以根据一个物体同一mesh或不同mesh的不同区域的属性差异来控制贴图上的属性产生不同&#xff0c;而没有贴图的话&#xff0c;一个物体只能使用一种…

Java Lambda表达式 匿名内部类 函数式接口(FunctionalInterface)

Java Lambda表达式定义背景示例匿名类实现Lambda表达式实现对比匿名类和Lambda实现Lambda表达式&#xff08;调用&#xff09;说明Lambda表达式的语法Java 1.8 新特性&#xff1a;函数式接口jdk 1.8 自带的函数式接口 &#xff08;举例&#xff09;定义 参考Oracle官网&#x…

目标检测6--R-FCN中的Position-Sensitive RoI Pooling

文章目录1.介绍2.Position-Sensitive Score Map 和 Position-Sensitive RoI Pooling3.源码参考资料欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; 1.介绍 论文: Region-based Fully Convolutional Networks 代码: R-FCN 本论文作者同9.De…

电子组装流水线MES系统实行条码质量追溯

在电子制造行业&#xff0c;保证生产过程的稳定性与对制造关键能力的改善与提升&#xff0c;是大多数制造企业的管理重心&#xff0c;而缺乏有效的方法与手段。MES系统即制造执行系统&#xff0c;是企业信息集成的纽带&#xff0c;企业实施敏捷制造战略&#xff0c;实现车间生产…

C++学习记录——십 STL初级认识、标准库string类

文章目录1、什么是STL2、STL简介3、什么是string类4、string类的常用接口说明1、常见构造函数2、容量操作3、迭代器4、其他的标准库的string类关于string类的内容&#xff0c;可以在cplusplus.com查看到。 1、什么是STL STL是C标准库的重要组成部分&#xff0c;不仅是一个可复…