类与对象(中篇)

news2025/1/21 10:24:32

类中六个默认成员函数

  • 构造函数
    • 基本概念
    • 构造函数特性
  • 析构函数
    • 基本概念
    • 析构函数特性
  • 拷贝构造函数
    • 基本概念
    • 拷贝构造函数特性
  • 赋值运算符重载
    • 概念引入
    • 运算符重载函数的特性
    • 部分运算符的重载函数
      • 判等
      • 赋值
      • 前置++ 、前置--
      • 后置++、后置--
  • const 成员函数
  • 取地址

只要生成一个类 ,那么这个类中就会默认创建6个成员函数。对于一个空类,看似类中什么都没有,但系统也会给它创建出来这6个成员函数。

构造函数

基本概念

回顾前边我们函数的使用

例如一个日期类:

在这里插入图片描述

可以看出,我们在定义类对象的时候都是先进行对象的定义,然后在进行初始化函数的调用操作,若同时定义多个对象,每一次定义对象之后都调用初始化函数会比较麻烦,因此我们想要在创建对象的时候同时进行一个初始化的赋值操作。

例如,我们在 C 中对变量的定义:

int main()
{
	//先定义后赋值
	int a;
	a = 10;

	//在定义同时初始化
	int b = 10;

	int c(10);

	return 0;
}

为了解决在定义类对象的同时进行对象的一个初始化操作,我们引出了构造函数的概念:

构造函数是一个特殊的成员函数,名字与类名相同,它是在创建类类型对象时由编译器来自动进行调用的,从而保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只被调用一次。

在这里插入图片描述

构造函数特性

(1)函数名与类名相同

例如,一个日期类中:

class Date {
public:
	//创建构造函数
	Date(int year, int month, int day)   //带参构造
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

(2)无返回值

在这里插入图片描述

(3)在创建对象时由编译器自动调用

在这里插入图片描述

也可以查看反汇编:

在这里插入图片描述

(4)构造函数可以重载

在这里插入图片描述

在定义类对象之后,会自动调用相应的构造函数:

class Date {
public:
	//创建构造函数
	Date(int year, int month, int day){
		_year = year;
		_month = month;
		_day = day;
		cout << "Date(int, int, int)" << this << endl;
	}
	//无参拷贝构造
	Date(){
		cout << "Date()" << endl;
	}
	void Print(){
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	//调用带参构造
	Date d1(2022, 11, 15);  

	//调用无参构造
	Date d2;

	return 0;
}

我们可以打印看看结果:

在这里插入图片描述

(5)若类中没有显式定义构造函数(用户没定义),则 C++ 编译器会自动生成一个默认的无参构造函数,一旦用户显式定义了则编译器就不会生成

class Date {
public:
//当前代码中并没有定义构造函数
	void Print() {
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

由于当前定义的 Date 类中对象成员变量都是 int 类型,编译器会判断有没有必要进行创建构造函数,此时没有资源进行管理,因此并没有创建出来相应的构造函数,因此在汇编代码中看到没有调用函数的 call 指令:

在这里插入图片描述

但若我们在 Date 类中添加一个自定义类型的对象,并且该自定义类型对象是具有显式定义的构造函数存在:

class Time {
public:
	Time(int hour = 1,int minute = 1,int second = 1)   //带参构造
	{
		_hour = hour;
		_minute = minute;
		_second = second;
	}
private:
	int _hour;
	int _minute;
	int _second;
};


class Date {
public:
	void Print() {
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;      //自定义类型的变量
};

在这里插入图片描述

此时在进行定义 Date 类对象时,调用了 Date 默认的构造函数(由系统自动生成的),这是由于 Date 类此时存在一个自定义类型 Time 类的对象,而 Time 类中包含有相应的全缺省构造,因此编译器在创建 Date 类对象会生成一个默认的无参构造函数,从而在默认构造函数内来调用 Time 类的构造函数。

(6)无参构造、全缺省构造----都称为默认构造函数,两者只能存在一个

class Date {
public:
	//全缺省构造
	Date(int year = 2022, int month = 11, int day = 15)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date()   //无参构造
	{}
	void Print() {
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

在这里插入图片描述

(7)编译器自动生成的默认构造函数在创建对象时调用,对象初始化值依旧为随即值,则默认的无参构造有什么用??

在这里插入图片描述

编译器自动生成的默认构造函数在创建对象时调用,对象初始化值依旧为随即值,但并不是说默认构造函数没用。

(1)假如我们在定义成员变量时就赋予了初始值:

此时调用的是系统自动生成的无参构造

在这里插入图片描述

(2)又如上边我们所举的例子,若在 Date 类中添加 Time 类的成员对象作为成员变量,则在编译时会自动生成默认的无参 Date 构造函数,因为 Time 类的构造函数是通过 Date 类的构造来进行调用的。

析构函数

我们在C语言阶段所学习到的栈、队列等的基本操作中,在定义栈结构时候会进行栈的初始化操作,并且在调用结束之后也会释放相应的栈空间,否则容易造成资源的泄露。

基本概念

析构函数与构造函数的功能相反,但析构函数并不是完成对象的销毁,局部对象的销毁工作是由编译器自动来完成的。析构函数是在对象调用结束时自动由编译器来进行调用,完成类对象的一些资源清理工作。

析构函数特性

(1)析构函数名是在类名前加~

class Date {
public:
	Date(int year, int month, int day)  //带参构造
	{
		_year = year;
		_month = month;
		_day = day;
	}

	~Date()     //对于当前的日期类来说,并没有资源需要进行清理
	{}
private:
	int _year;
	int _month;
	int _day;
};

(2)无参数无返回值

在日期类中的析构函数:

~Date()    
	{}

(3)一个类有且仅有一个析构函数

(4)对象生命周期结束时,C++编译器会自动调用析构函数

假如我们给定一个栈结构:

class Stack {
public:
	Stack() {   //无参构造
		_arr = (int*)malloc(sizeof(int) * 10);
		_capacity = 10;
		_top = 0;
	}
	void Push(int data) {
		//checkcapacity();    //不考虑扩容
		_arr[_top++] = data;
	}
	void Pop() {
		_top--;     //不考虑空
	}
	int Size() {
		return _top;
	}
	int Top() {
		return _arr[_top - 1];
	}
	bool Empty(){
		return 0 == _top;
	}
	~Stack()
	{
		if (_arr) {
			free(_arr);
			_arr = nullptr;
			_capacity = _top = 0;
		}
	}
private:
	int* _arr;
	int _capacity;
	int _top;
};
void TestStack()
{
	Stack s;
}

int main()
{
	TestStack();
	return 0;
}

在这里插入图片描述

(5)若用户未显式定义析构函数,则编译器会生成一个默认的析构函数

如果对象中没有涉及到任何资源管理时,该类的析构函数可以不用给出(因此在用户没有定义析构函数时,系统判断没有资源需要进行释放,因此不会生成默认的析构函数)

class Date {
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Show()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
void Test()
{
	Date d1(2022, 11, 15);
	d1.Show();
}
int main()
{
	Test();           //生命周期结束不会调用析构
	return 0;
}

在这里插入图片描述

但若当前程序存在需要释放的类资源时,则会调用相应的析构函数(系统默认生成)来进行资源清理:

class Stack {
public:
	Stack() {   //无参构造
		_arr = (int*)malloc(sizeof(int) * 10);
		_capacity = 10;
		_top = 0;
	}
	void Push(int data) {
		//checkcapacity();
		_arr[_top++] = data;
	}
	void Pop() {
		_top--;
	}
	int Size() {
		return _top;
	}
	int Top() {
		return _arr[_top - 1];
	}
	bool Empty(){
		return 0 == _top;
	}
~Stack()
	{
		if (_arr) {
			free(_arr);
			_arr = nullptr;
			_capacity = _top = 0;
		}
	}
	
private:
	int* _arr;
	int _capacity;
	int _top;
};

class MyQueue {
	//模拟栈实现队列
public:
	MyQueue() {}
	void Push() {}
	void Pop() {}
	int Front() {}
	int Back() {}
	bool Empty() {}
private:
	//需要借助两个栈结构
	Stack s1;
	Stack s2;
};


void TestStack()
{
	MyQueue q;
}

int main()
{
	TestStack();
	return 0;
}

由于此时创建了两个栈结构,因此在生命周期结束之后会调用两次 ~Stack

(6)析构函数的析构顺序与构造顺序相反---------先构造的后析构(释放)

先进行构造的对象会先进行析构。


class Stack {
public:
	Stack() {   //无参构造
		_arr = (int*)malloc(sizeof(int) * 10);
		_capacity = 10;
		_top = 0;
		cout << "构造 Stack()" << this << endl;
	}
	void Push(int data) {
		//checkcapacity();
		_arr[_top++] = data;
	}
	void Pop() {
		_top--;
	}
	int Size() {
		return _top;
	}
	int Top() {
		return _arr[_top - 1];
	}
	bool Empty() {
		return 0 == _top;
	}
	~Stack()
	{
		if (_arr) {
			free(_arr);
			_arr = nullptr;
			_capacity = _top = 0;
		}
		cout << "析构 ~Stack() " << this << endl;
	}
private:
	int* _arr;
	int _capacity;
	int _top;
};

void Test()
{
	Stack s1;
	Stack s2;
}
int main()
{
	Test();
	return 0;
}

在这里插入图片描述

练习题********

在这里插入图片描述
在这里插入图片描述

拷贝构造函数

基本概念

在创建一个对象时候能否创建一个一样的对象出来呢?

在 C 语言阶段,我们可以用一个已有的对象来创建一个一样的新对象出来

在这里插入图片描述

因此,我们思考在创建一个类对象时,能否采用相同的方法来实现新对象的创建?

在这里插入图片描述
可以看出来,在创建类对象时候也是可以通过已有对象来实现新对象的创建,但它的底层是如何实现的呢?因此引入拷贝构造函数的基本概念。

拷贝构造函数
用一个已有的对象来创建一个新的对象,并且新对象的内容与已有对象内容相同

拷贝构造函数特性

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

拷贝构造函数名与类名相同,没有返回值,且它的参数只有一个(用已有对象创建新对象):

class Date {
public:
	Date(int year, int month, int day)   //构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}

	Date(const Date& d)   //拷贝构造函数
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	~Date()
	{}

private:
	int _year;
	int _month;
	int _day;
};

拷贝构造函数名与构造函数名相同,且两者都没有返回值类型,函数参数列表不同,因此构成了函数的重载。

(2)拷贝构造函数的参数只有一个并且必须使用引用参数,因为使用传值方式会造成无穷递归调用

Date(const Date& d)   //拷贝构造函数
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

拷贝构造实现的是用一个已有的对象来创建一个新的对象,因此原对象在函数内是不能够进行修改的,故采用 const 进行修饰。

引用传参一方面是效率更高,另一方面是为了防止传值造成的无穷递归调用的产生

在这里插入图片描述

由于引用相当于是一个变量的别名,代表的依旧是原对象,因此通过传引用会大大提升函数运行效率,同时避免了无穷递归调用。

(3)若未显式定义拷贝构造函数,则编译器会自动生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储字节完成拷贝---------浅拷贝(值拷贝)

但是编译器在使用已有对象创建新对象的同时会考虑是否有必要生成拷贝构造函数,若不存在资源拷贝过程,编译器就不会生成默认的拷贝构造函数,但依旧会完成了值拷贝的过程。

1)Date 类中显式定义拷贝构造函数时,编译器会自动调用拷贝构造函数来实现

在这里插入图片描述

我们可以通过反汇编来查看:

在这里插入图片描述

2)Date 类中用户没有显式定义构造函数时,由于 Date 类中成员变量类型都是 int ,不存在资源的拷贝,因此编译器认为没有必要生成一份默认的拷贝构造函数,但是依旧会完成内容的拷贝

在这里插入图片描述

(4)既然在用户没有显式定义拷贝构造函数时候,编译器会默认生成一个拷贝构造函数,那么我们是否还需要显式来定义??

对于编译器默认生成的拷贝构造函数,它只是实现的内容的拷贝,也就是浅拷贝-----将原对象的内容原封不动的拷贝给新对象,但是这种拷贝就一定完全正确吗?

当我们的类中存在资源内容时,来看看拷贝构造函数的实现是否合适:

class String {
public:
	String(const char *str = "hello")   //带参构造函数
	{
		_str = (char*)malloc(sizeof(char)*(strlen(str) + 1));
		strcpy(_str, str);
	}

	~String()
	{   //此时存在资源需要进行清理
		if (_str) {
			free(_str);
			_str = nullptr;
		}
	}
private:
	char* _str;
};

int main()
{
	String s1("hello world!\n");   //调用构造函数

	String s2(s1);        //会调用默认生成的拷贝构造函数

	return 0;
}

在这里插入图片描述

可以看出此时编译器确实生成了一个默认的拷贝构造函数,并且实现了内容的拷贝,但是在运行最后却发生了报错,这是为什么?

在这里插入图片描述

我们可以查看监视窗口来寻找问题所在:

在这里插入图片描述

由此此时 String 类中存在资源需要清理,故在调用结束之后会自动调用析构函数,先构造的后析构,因此先析构 s2 ,后析构 s1 发生报错,这是为什么?

解答:
在通过 s1 对象来创建 s2 对象的时候,调用的是编译器默认生成的拷贝构造函数 ,确实完成了相应的内容拷贝过程,但是我们发现创建出来的两个对象的地址居然是一样的,这就导致了在程序运行结束时候析构函数进行析构的时候出现问题(两次析构清理的是同一份空间)----------------------- 由此可见,编译器默认生成的拷贝构造函数仅仅是浅拷贝,只是将原对象的内容原封不动的拷贝给新对象,这是不可取的,因此我们应该显式的定义拷贝构造函数来完成拷贝工作

赋值运算符重载

概念引入

回归 C 语言当中,我们在定义变量时候:

在这里插入图片描述

那么在创建类对象时候,能够采用相同的思路来进行?

class Date {
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	~Date()
	{}

private:
	int _year;
	int _month;
	int _day;
};




int main()
{
	Date d1(2022, 11, 27);


	//下列创建是否正确?

	Date d2(d1);
	Date d3 = d1;

	Date d4;
	d4 = d1;

	return 0;
}

在这里插入图片描述

运行程序发生了报错这是为什么?

在前边我们谈到了拷贝构造函数,它是用已有的对象来创建新对象,因此此处的 d2,d3 对象的创建显然是调用拷贝构造函数的
而 d4 对象是先进行的创建,然后再通过 d1 对象来进行赋值操作,程序报错是因为此时的对象并不简简单单是某一中数据类型(int 、char、double…),此时的对象是类类型的对象,因此需要进行赋值运算符的重载操作才能够进程赋值。

C++中为了提升代码的可读性引入了运算符重载。
运算符重载是具有特殊函数名的函数,具有返回值类型,函数名以及参数列表,其返回值类型与参数列表与普通函数类似。

返回值类型 operator操作符(参数列表)

赋值运算符的重载

Date& operator=(const Date& d)
	{
		if (&d != this) {
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}

在这里插入图片描述

注意

(1)返回值类型为 Date&

在进行赋值操作时,有可能存在连续赋值的情况存在,因此返回值类型应该与对象类型相同为 Date ,采用 &引用减少的值拷贝

在这里插入图片描述

若返回值类型为 void ,则在进行连续赋值时会报错,因为首先完成了 d2=d1,d1给 d2 的赋值,由于没有返回值,因此 d3 的赋值无法正常进行:

在这里插入图片描述

(2)参数列表只有一个,且为 const

因为此时运算符重载函数是位于类内部,属于类内成员函数,而成员函数具有一个默认的参数 *this 作为第一个参数,实际参数 Date& d 为第二个参数,由于调用赋值运算符重载函数是用第二个参数给第一个参数*this进行赋值,所以此处的 d 是不应该被修改的,因此我们采用 const 来进行修饰

(3)&d!=this

*this 指向的是当前操作的对象,为了防止产生自己给自己赋值的情况,因此我们进行一个检测

(4)return *this

返回值应该返回的是被赋值的对象,此时是 第二个参数 d 给 第一个默认的参数*this 进行赋值操作,因此返回的是 *this

运算符重载函数的特性

(1)不能通过链接其他符号来创建新的操作符:operator@

(2)重载操作符必须有一个类类型或是枚举类型的操作数

在这里插入图片描述

(3)用于内置类型的操作符,其含义是不能进行改变的

例如,内置类型的算数 + ,表示加法操作,在进行重载时不能改变其加法含义

(4)用作类成员的重载函数时,其形参看起来比操作数数目少一(因为类中成员函数具有一个默认的 *this 指针,指向当前操作的对象)

(5)不能进行重载的运算符: .* 、 :: 、sizeof、 ?:(三目运算)、.

部分运算符的重载函数

判等

bool operator==(const Date& d)
	{
		return _year == d._year && _month == d._month && _day == d._day;
		//等价表示
		return this->_year == d._year && this->_month == d._month && this->_day == d._day;
	}

在这里插入图片描述

赋值

Date& operator=(const Date& d)       //存在默认的第一个参数 *this
	{
		if (&d != this) {      //防止自己给自己赋值
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}

前置++ 、前置–

前置++

int a=0;
int b=++a;        // a 先进行自增,然后将修改后的值赋给 b
Date d1(2022, 11, 27);
Date d2 = ++d1;    //d1 先进行自增,后将修改后的值赋给 d2
  

在调用运算符重载函数时,返回的是自增之后的值:

Date& operator++()  //前置++
	{
		_day += 1;
		return *this;
	}

注意

(1)返回值 Date&

由于返回的是自增之后的值,因此直接返回修改之后的 *this,采用 & 减少了值拷贝过程

(2)参数列表为空

由于前置++,是在原对象的基础上进行自增并反正自增之后的结果,从始至终仅对一个对象的内容进行操作,因此不需要传递参数,直接操作默认的第一个参数 *this 即可

(3)return *this

操作的是 *this ,返回的也是被操作的对象 *this

在这里插入图片描述

前置–

原理同前置++

在这里插入图片描述

后置++、后置–

后置++

int a=0;
int ret = a++;      //前置++,表示先使用 a 的值,后对 a 自增
Date d1(2022, 11, 27);
Date d2 = d1++;    //会先将 d1 的内容赋值给 d2,然后 d1 自增

因此在调用运算符重载函数时,返回的是自增之前的值:

Date operator++(int)   //后置++         d1++
	{
		Date tmp(*this);      //保存修改之前的值
		_day += 1;
		return tmp;           //由于 tmp 是一个临时变量,因此返回值应该为值类型-------具有一次值拷贝过程
	}

注意
(1)返回值类型

由于返回的 tmp 是一个临时变量,因此返回值应该为值返回,具有一次值拷贝过程

(2)参数 int

由于前置++ 与后置++ 所对应的运算符重载函数只有返回值类型不同,不能构成函数的重载,因此给后置 ++ 添加一个虚参数 int ,使它能够与前置++形成重载

在这里插入图片描述

后置–

原理同后置++

在这里插入图片描述

const 成员函数

类中成员函数的第一个默认参数 *this 的类型为 const 类类型 * this,表明 *this
所指向的内容不能进行修改

//const 成员函数,表明成员变量不能被修改,const 修饰成员函数 实际上是在修饰 this指针
	void Print()const         
	  //此时 this  指针的类型 :   const Date* const         指向和内容都不能被修改
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

取地址

class Date {
public:
	Date(int year, int month, int day) {
		_year = year;
		_month = month;
		_day = day;
	}
	Date()
	{}

	//拷贝构造
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
    Date* operator&()       //取地址运算符重载:普通变量的取地址
	{
		return this;  //this 指针中保存的是当前变量的地址,因此返回值用 * 来接收
	}
	
	const Date* operator&()const      //取地址运算符重载:const 变量的取地址,表明指向和值都不能修改
	{
		return this;    //this 指针中保存的是当前变量的地址
	}
private:
	int _year;
	int _month;
	int _day;
};



int main()
{
	Date d(2022, 11, 20);
	Date*p = &d;          //调用普通类型的取地址函数


	const Date d1(2022, 11, 21);         //const 类型表明值内容不能进行修改
	const Date* p1 = &d1;         //调用 const 变量的取地址函数


	return 0;
}

注意

//const 对象不能调用非 const 成员函数-----------防止函数内部修改数据内容
//非 const 对象可以调用 const 成员函数
//const 成员函数内部不可以调用其他的非 const 成员函数
//非 const 成员函数内可以调用其他的 const 成员函数

ps:
欢迎评论思路哦~~

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

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

相关文章

iOS_Custom Transition Animation 自定义转场动画

文章目录1、push-pop 动画协议2、present-dismiss 动画协议3、实现转场动画协议3.1 动画时长3.2 push or present animation (显示动画)3.3 动画结束3.4 pop or dismiss animation (消失动画)4、UIPresentationController4.1 设置presentVC的frame4.2 present 动画4.3 dismiss …

Docker快速安装Oracle 12c

【Oracle系列3】Docker快速安装Oracle 12c 背景 现在还很多企业用12c&#xff0c;以这个版本为例&#xff0c;介绍docker快速启动Oracle并做实验 步骤 1、docker环境的安装&#xff08;略&#xff09; 2、查询镜像&#xff0c;挑选镜像 docker search oracle结果 StoneM…

阿里P8架构师都在学习参考的SpringCloud微服务实战文档

我一直在使用Spring Boot、Spring Data等框架来进行开发工作。 作为一名Spring系列的忠实粉丝&#xff0c;我自然希望能够有更多的开发者参与进来&#xff0c;于是自己坚持写Spring Cloud相关的文章&#xff0c;并且将文章涉及的代码整理后放在GitHub上分享。 这使我得到了很…

【Hack The Box】Linux练习-- Luanne

HTB 学习笔记 【Hack The Box】Linux练习-- Luanne &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月24日&#x1f334; &#x1f3…

零基础搭建基于知识图谱的电影问答系统

零基础搭建基于知识图谱的电影问答系统一、项目准备二、项目数据三、训练问题分类器四、准备问答模板五、搭建webapp六、问题预处理一、项目准备 首先需要一款python编译器&#xff0c;本人选用的是PyCharm&#xff0c;搭建好Python环境&#xff1b;安装第三方依赖库&#xff…

【Hack The Box】linux练习-- Delivery

HTB 学习笔记 【Hack The Box】linux练习-- Delivery &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月17日&#x1f334; &#x1…

黄佳《零基础学机器学习》chap1笔记

黄佳 《零基础学机器学习》 chap1笔记 这本书实在是让我眼前一亮&#xff01;&#xff01;&#xff01; 感觉写的真的太棒了&#xff01; 文章目录黄佳 《零基础学机器学习》 chap1笔记第1课 机器学习快速上手路径—— 唯有实战1.1 机器学习族谱1.2 云环境入门实践&#xff1a;…

ERD Online 4.0.4 元数据在线建模(免费、私有部署)

❝ fix(erd): 修改表名、模块名自定义提示fix(erd): 支持自定义表名显示格式fix(erd): 升级ant到5.0.1版本fix(erd): 修复PDMan导入类型列为空fix(erd): 增加类型列宽度&#xff0c;避免类型显示不全fix(erd): 修复表设计报undefine异常fix(erd): 修复版本比对&#xff0c;出现…

二分搜索算法框架解析

文章目录 一、寻找一个数&#xff08;基本的二分搜索&#xff09;二、寻找左侧边界的二分搜索三、寻找右侧边界的二分查找总结 一、寻找一个数&#xff08;基本的二分搜索&#xff09; 这个场景是最简单的&#xff0c;可能也是大家最熟悉的&#xff0c;即搜索一个数&#xf…

2023年天津财经大学珠江学院专升本经济学专业课考试大纲

天津财经大学珠江学院2023年高职升本科专业课考试《经济学》考试大纲一、本大纲系天津财经大学珠江学院2023年高职升本科《经济学》课程考试大纲。所列考试范围出自郑健壮、王培才主编的教材《经济学基础&#xff08;第二版&#xff09;》&#xff0c;清华大学出版社&#xff0…

win10通过Docker搭建LNMP环境全流程

win10通过Docker搭建LNMP环境全流程 下载安装docker desktop 由于博主环境已经安装好了&#xff0c;一些异常设置&#xff0c;暂且略过 根据官方教程下载docker desktop执行文件.exe 注意尽量不要把docker安装到C盘&#xff0c;除非你的C盘很大&#xff0c;具体可以参考文章 …

初识 Spring 框架

文章目录一、Spring 介绍二、Spring 下载安装三、编写入门程序1.项目文件构架2.引入相关依赖3.创建实体类4.Spring 配置文件5.编写测试类四、控制反转与依赖注入1.控制反转概念2.依赖注入概念3.依赖注入的类型4.依赖注入的应用一、Spring 介绍 Spring 是由 Rod Johnson 组织和…

计算机毕设题目设计与实现(论文+源码)_kaic

毕业设计(论文)题目 高校图书馆座位预约选座微信小程序设计与实现 基于防火墙的访问控制系统的设计与实现 基于区块链的农产品追溯系统设计与实现 学生公寓楼改造布线系统规划与设计 智能家居网络设计与实现“互联网”农村精准扶贫共享平台的设计与实现“智慧健康少儿成长平台”…

Linux内核——门相关入门知识

为什么20位的寻址可以达到1MB&#xff1f; &#x1f512; 点击查看答案 &#x1f512; 拆分如下的段描述符&#xff1a; 0000000000000000 00cf9b000000ffff 00cf93000000ffff 00cffb000000ffff 00cff3000000ffff 80008b04200020ab ffc093dff0000001 0040f30000000fff 0000f20…

TypeScript开启

TypeScript是什么&#xff1f; typescript是以JavaScript为基础构建的语言&#xff0c;是一个Javascript的超集&#xff0c;可以在任何支持JavaScript的平台中执行&#xff0c;typescript扩展了JavaScript&#xff0c;并添加了类型。 注意&#xff1a;ts不能被js直接解析执行&…

MySQL的join你真的了解吗!!!

1.测试用例数据库信息 本文章采用的数据库结构&#xff0c;以及MySQL版本&#xff1a;5.7 t1 表&#xff0c;有一个主键id&#xff0c;字段a&#xff0c;字段b。 &#xff08;此表建立了一个索引a&#xff09; 数据大约1000条 t2 表&#xff0c;有一个主键id&#xff0c;字段…

C++标准库分析总结(十一)——<适配器>

目录 1 适配器简介 2 适配器使用分类 2.1 容器适配器 2.2 函数适配器 2.2.1 常见的函数适配器 2.2.2 bind2nd 2.2.3 not1 2.2.4 新型适配器bind 2.3 迭代器适配器 2.3.1 reverse_iterator 2.3.2 insert_iterator 2.4 X适配器 2.4.1 ostream_iterator 2.4.2 istre…

BUUCTF-babyheap_0ctf_2017

checksec 标准堆菜单 IDA Allocate void __fastcall sub_D48(__int64 a1) {int i; // [rsp10h] [rbp-10h]int v2; // [rsp14h] [rbp-Ch]void *v3; // [rsp18h] [rbp-8h]for ( i 0; i < 15; i ){if ( !*(_DWORD *)(24LL * i a1) ){printf("Size: ");v2 sub_1…

【云原生】无VIP稳定性和可扩展性更强的k8s高可用方案讲解与实战操作

文章目录一、概述二、架构三、开始部署1&#xff09;节点信息2&#xff09;前期准备&#xff08;所有节点&#xff09;1、配置hosts2、配置互信3、时间同步4、关闭防火墙5、禁用SELinux6、关闭swap7、设置bridge-nf-call-iptables3&#xff09;安装容器docker&#xff08;所有节…

C++标准库分析总结(十)——<仿函数/函数对象>

目录 1.functor仿函数简介 2 仿函数的分类 3 仿函数使用 4 仿函数可适配的条件 1.functor仿函数简介 仿函数是STL中最简单的部分&#xff0c;存在的本质就是为STL算法部分服务的&#xff0c;一般不单独使用。仿函数&#xff08;functors&#xff09;又称为函数对象&…