C++ 类和对象 (中)

news2024/11/30 2:31:02

作者:@小萌新
专栏:@C++初阶
作者简介:大二学生 希望能和大家一起进步
本篇博客目标:梳理自己六个小时学到的知识 并且将类和对象知识分享给大家
在这里插入图片描述
专注的去做一件事
如果累了就去休息

C++ 类和对象 中

  • 本章学习目标
  • 前言
  • 一. 构造函数
    • 1.1 概念
    • 1.2 特性
      • 1.2.1 带参构造函数
      • 1.2.2 无参构造函数
      • 1.2.3 缺省参数构造函数
      • 1.2.4 无构造函数
    • 1.3 构造函数的作用
    • 1.4 C++11的补丁
  • 二. 析构函数
    • 2.1 概念
    • 2.2 特性
    • 2.3 自动析构
  • 三. 拷贝函数
    • 3.1 概念
    • 3.2 深拷贝 浅拷贝
    • 3.3 拷贝构造函数典型调用场景
      • 使用已存在对象创建新对象
      • 函数参数类型为类类型对象
      • 函数返回值类型为类类型对象
  • 四. 赋值运算符重载
    • 4.1 概念
    • 4.2 使用方法(运算重载)
    • 4.3 赋值重载
    • 4.4 默认的赋值重载符
    • 4.5 赋值重载的总结
  • 总结

本章学习目标

  1. 类的六个默认成员函数是什么?
  2. 详讲构造函数
  3. 详解析构函数
  4. 详解拷贝构造函数
  5. 详解赋值运算符重载函数

前言

如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?
其实并不是这样子,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。
默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

这是比较官方的解释 通俗语言解释咋回事捏

就是说你只要生成了一个类 哪怕是空的 编译器都会给你生成下面图中这六个默认成员函数

class Date {};

在这里插入图片描述

但是呢 编译器写的默认函数很多时候不能满足我们的要求

那这个时候是不是就要我们自己写了

那么要怎么写这六个默认函数呢?

来 让我们带着这个问题进入下面的章节

一. 构造函数

1.1 概念

对于下面的Data类

我们这里实现了两个函数 分别是初始化和打印

class Date
{
public:
	void Init(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;
};



int main()
{
	Date d1;
	d1.Init(2022, 11, 3);
	d1.Print();

	return 0;
}

实现效果如下

在这里插入图片描述

但是呢 每次初始化对象的时候都要调用Init函数是不是很烦啊

并且容易忘记是不是

那么这个时候 我们的构造函数就应运而生了

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

这里是对于构造函数简单的一个介绍

1.2 特性

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任
务并不是开空间创建对象,而是初始化对象

构造函数具有以下的特性 在罗列出来之后我们会一一解释

  1. 函数名和类名相同
  2. 无返回值
  3. 对象实例化时编译器自动调用对应的构造函数
  4. 可以函数重载(作用就是我们可以提供多个构造函数 提供多种初始化方法 )
  5. 如果类中没有定义的化 编译器会默认生成(其实在上面的学习目标中已经讲了)

还是老样子 先上代码

1.2.1 带参构造函数

在这里插入图片描述
我们可以看到 完全符合构造函数的描述

在这里插入图片描述
所以说这就是一个标准的带参构造函数

它的初始化方式是这样子的

在这里插入图片描述

我们来看看运行结果怎么样

在这里插入图片描述

可以完美运行

1.2.2 无参构造函数

这个和带参构造函数相差不了多少

我们这里简单写一下

这就是一个简单的无参构造函数

在这里插入图片描述
并且这两个函数构成函数重载
在这里插入图片描述

我们来看看 最后运行结果是什么样子

在这里插入图片描述
我们发现最后是不是一个就是打印我们设定的默认值 一个就是打印我们传递的值

1.2.3 缺省参数构造函数

这个写法也很简单

在这里插入图片描述
最下面是不是就是一个简单的构造函数啊

那么这里有三个问题来了

首先 它们构成函数重载嘛?

其次 我们可以这么使用它嘛?

什么场景下可以使用呢?

第一个问题 它们构成函数重载

构不构成重载首先看参数相同不相同

它们之间的参数是不同的吧

所以说它们否成函数重载

第二个问题 我们可以这么使用它嘛?

不可以!

因为当我们不传参进去的时候 编译器会不知道调用哪个函数 从而产生歧义

第三个问题 我们什么时候可以使用它呢?

答案是屏蔽掉一个重载函数

然后不使用能够产生歧义的方式传参

就像这样

在这里插入图片描述

1.2.4 无构造函数

在这里插入图片描述
我们将上面的函数转到反汇编之后会发现 在进入初始化d1的确实调用了函数

那么假设我们没有默认构造函数呢

在这里插入图片描述
就像这样 我们进入反汇编看看

在这里插入图片描述
在这里插入图片描述
我们可以发现 这里还是调用了call函数

这是不是就说明 假设我们没有设置默认构造函数 系统会自己默认生成啊

在这里插入图片描述
但是我们可以发现这里的数据是不是不太聪明的样子啊

综合上面的几种情况 我们可以验证上面的特性并且得出结论

**当我们没有写构造函数的时候系统会默认生成一个构造函数 但是呢这个构造函数和我们预期的值可能会有所差异 所以这里还是推荐构造函数的值自己来写 **

1.3 构造函数的作用

对于栈这种数据结构来说 初始化是必要的

因此在c++中我们可以使用构造函数对其进行初始化

我们来看代码

在这里插入图片描述

我们可以进入到调式看看效果怎么样

在这里插入图片描述
另外我们可以发现 this指针就是指向我们的结构体的
在这里插入图片描述
如果这里不初始化就会报错 (没有开辟动态内存嘛)
在这里插入图片描述

1.4 C++11的补丁

这里构造函数的初始化规则很奇怪 它只会对于自定义类型初始化 对于内置类型不会初始化

在C++11的补丁当中给予了这么一个规则

即:内置类型成员变量在类中声明时可以给默认值。

类似这样子
在这里插入图片描述
我们可以发现 这个时候没有了构造函数也不会报错 非常的方便
在这里插入图片描述

二. 析构函数

2.1 概念

学习了构造函数之后我们知道了函数是如何初始化的了
那么问题来了 最后时候函数是如何销毁的呢?
就像栈 如果我们忘记调用destroy了是不是就会出现内存泄漏的问题啊

这里C++中也给出了解决方案 这就是析构函数

2.2 特性

还是一样 在罗列之后我们会在下面一一解释

  1. 析构函数名是在类名前加上字符 ~
  2. 无参数无返回值类型
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构
    函数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数
class Stack
{
public:
	Stack(int capacity = 4)
	{
		_a = (int*)malloc(sizeof(int) * capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}

		_top = 0;
		_capacity = capacity;
	}
	~Stack()
	{
		free(_a);
		_a = nullptr;
	}
	void Push(int x)
	{
		//……
		_a[_top++] = x;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};

int main()
{

	Stack s;
	s.Push(1);

	return 0;
}

我们运行下看看

在这里插入图片描述

我们可以发现 这里确实是默认调用了析构函数的

2.3 自动析构

class Stack
{
public:
	Stack(int capacity = 4)
	{
		cout << "Stack(int capacity = 4)" << endl;

		_a = (int*)malloc(sizeof(int)*capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}

		_top = 0;
		_capacity = capacity;
	}

	~Stack()
	{
		cout << "~Stack()" << endl;

		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}


private:
	int* _a;
	int _top;
	int _capacity;
};

class MyQueue {
public:
	void push(int x)
	{
		//_pushST.Push(x);
	}

private:
	Stack _pushST;
	Stack _popST;
};

// 面向需求:编译器默认生成就可以满足,就不用自己写,不满足就需要自己写
// Date Stack的构造函数需要自己写
// MyQueue构造函数就不需要自己写,默认生成就可以用

// Stack的析构函数,需要我们自己写
// MyQueue Date就不需要自己写析构函数,默认生成就可以用

int main()
{
	MyQueue q;

	return 0;
}

在这里插入图片描述

我们可以发现 在我们定义MyQueue的时候 并没有写析构函数

而是系统自己析构了

三. 拷贝函数

3.1 概念

在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎。

在这里插入图片描述
那么在创建对象时候能不能创建一个和对象一模一样的新对象呢?

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存
在的类类型对象创建新对象时由编译器自动调用。

我们先来看看拷贝函数的形式

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


	Date(const Date& d)//拷贝构造
	{
		cout << "拷贝构造" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

int main()
{
	Date d1(2022, 9, 22);
	d1.Print();

	//拷贝一份d1
	Date d2(d1); //拷贝构造,拷贝初始化
	d2.Print();



	return 0;
}

我们来运行下看看结果怎么样

在这里插入图片描述

我们发现 这里是不是用的传引用传值啊

那么大家仔细想想 如果我们使用传值传递呢 这样子可以嘛?

我们来试试看

在这里插入图片描述

这里vs2022编译器上做了优化啊 在以前的编译器上如果你使用传值传参的话是会无限递归下去的

为什么呢?

我们将函数改成这个结构 大家是不是好理解一点

在这里插入图片描述

这个结构觉不觉得很眼熟

是不是跟我们学递归的时候写的函数十分类似啊

在这里插入图片描述
是不是这样子就好理解了

3.2 深拷贝 浅拷贝

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

  2. 拷贝函数参数有且只能有一个 并且必须要是类型对象的引用 不能是传值传递

  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);
	return 0;
}

我们来看看它的debug过程

在这里插入图片描述

我们可以发现 我们这里把拷贝函数屏蔽掉之后依然开始拷贝d1(这就是因为系统生成了默认的拷贝函数了)

我们将这种拷贝类型叫做浅拷贝

那么既然系统会给我们写好拷贝函数 是不是我们不用写了呢?

正确答案是不是的

因为系统给我们写的拷贝是按照字节序的拷贝

遇到某种情况可能会遇到bug

class Stack
{
public:
	Stack(int capacity = 4)
	{
		cout << "Stack(int capacity = 4)" << endl;

		_a = (int*)malloc(sizeof(int)*capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}

		_top = 0;
		_capacity = capacity;
	}
	~Stack()
	{
		cout << "~Stack()" << endl;

		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}

	void Push(int x)
	{
		// ....
		// 扩容
		_a[_top++] = x;
	}

private:
	int* _a;
	int _top;
	int _capacity;
};
 
// 需要写析构函数的类,都需要写深拷贝的拷贝构造              Stack
// 不需要写析构函数的类,默认生成的浅拷贝的拷贝构造就可以用   Date/MyQueue

class MyQueue {
public:
	void push(int x)
	{
		_pushST.Push(x);
	}
private:
	Stack _push
	Stack _popST;
	size_t _size = 0;
};

int main()
{
	Stack st1;
	st1.Push(1);
	st1.Push(2);
	// 1 2

	Stack st2(st1); 
	st2.Push(10);

	st1.Push(3);
	// 1 2 10


	MyQueue q1;
	MyQueue q2(q1);


	return 0;
}

我们可以看到当我们没有拷贝的时候函数是可以正常运行的

在这里插入图片描述
然后我们在拷贝下试试

在这里插入图片描述
我们可以发现 当我们使用拷贝函数的时候 是不是就直接报错了啊 这是为什么呢?

在解答这个问题之前我们先来看看这个操作

在这里插入图片描述
这里我们可以发现是没有问题的 那么我们接着下一步操作呢

我们再释放一次a

在这里插入图片描述
这里是不是报了一个和上面一模一样的错误啊

那么我们就很明确了 上面的函数肯定是对于一块空间多次释放了

那么这是为什么呢?

我们来看图

在这里插入图片描述
之后我们释放s1的时候释放了这一块动态开辟的内存

释放s2的时候又释放了一次 所以当然会报错啦

那么这个时候我们就要自己写一个深拷贝

在这里插入图片描述
这个时候我们的深拷贝会自己开辟一块动态内存 是不是就不会报错了啊

在这里插入图片描述

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

3.3 拷贝构造函数典型调用场景

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

这个很简单 上面已经给出例子了

在这里插入图片描述

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

在这里插入图片描述

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

		MyQueue q3 = q1;

就比如说这一行代码

四. 赋值运算符重载

4.1 概念

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其

返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

**函数名字为:**关键字operator后面接需要重载的运算符符号。

**函数原型:**返回值类型 operator操作符(参数列表)

有点怪怪的是吧

我们先来看它的一个使用场景

这里我们定义了一个日期类 要看它的天数是否相同(年月日都相同)

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	
private:
	// 基本类型(内置类型)
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1(2022, 9, 21);
	Date d2(2022, 9, 22);

	cout << (d1 == d2) << endl;
	
	return 0;
}

在这里插入图片描述

我们可以发现 这里使用了“==” 操作符比较不了

这是为什么呢?

其实仔细想想就能明白 因为编译器并没有能够很好的处理自定义类之间的比较关系

那么这个时候就应该我们的operator函数上场了

4.2 使用方法(运算重载)

我们使用operator之后发现报了个这样子的错误 (参数太多)
在这里插入图片描述
当然啦 这是语法规定

那么只有一个参数这个时候我们应该怎么比较呢?

那么现在我们的this指针就派上用场了

	bool operator==( const Date& d2)
	{
		// 这里为了方便大家理解只写一个this 其他地方不写 
		return this->_year == d2._year
			&& _month == d2._month
			&& _day == d2._day;
	}

这里函数写法如上

我们再试试==能不能用

在这里插入图片描述
在这里插入图片描述
我们发现 这样子就可以完美运行了

这里我们要注意的点有

不能通过连接其他符号来创建新的操作符:比如operator@ 重载操作符必须有一个类类型参数
用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
. :: sizeof ?: .注意以上5个运算符不能重载。这个经常在笔试选择题中出现。*

4.3 赋值重载

顾名思义嘛 我们这里要讲关于赋值重载的问题

那么对比于运算重载赋值重载有什么特点呢?

我们这里先给出以下格式 在后面的讲解中会逐个解释它们

参数类型:const T&,传递引用可以提高传参效率
返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
检测是否自己给自己赋值
返回*this :要复合连续赋值的含义

我们先来看以下代码

	void operator=(const Date& d)  //&:避免拷贝构造
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

在这里插入图片描述
简单验证下 说明我们写的 = 赋值运算符是对的
在这里插入图片描述
这里简单解释下

因为是引用传参数 所以说d是d2的别名 而因为是d1调用的函数 所以说this指针是指向d1的

我们都知道对于赋值操作来说 是要满足链式赋值的

比如说

在这里插入图片描述
那么我们来看看我们重载的赋值运算满足不满足这个规律

在这里插入图片描述
我们可以发现 报错了 这是为什么呢?

看看操作信息 这是由于我们=操作符重载后的返回值是void

我们修改下 改成Date看看

在这里插入图片描述
我们发现 设定了返回值之后就可以完美运行了

4.4 默认的赋值重载符

我们上面已经介绍过 六大默认函数都有一个特点 就是如果你不写 编译器就会默认给你写一个

那么我们来看看系统给的赋值操作符是什么样子的

在这里插入图片描述
咦 好像也可以完成我们的任务

那么是不是系统给的默认赋值重载符就没有问题呢?

这里给出我们之前的栈函数

class Stack
{
public:
	Stack(int capacity = 4)
	{
		cout << "Stack(int capacity = 4)" << endl;

		_a = (int*)malloc(sizeof(int)*capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capacity = capacity;
	}
	~Stack()
	{
		cout << "~Stack()" << endl;

		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
	void Push(int x)
	{
		// ....
		// 扩容
		_a[_top++] = x;
	}
	
private:
	int* _a;
	int _top;
	int _capacity;
};
void TestStack()//析构两次,且内存泄漏
{
	Stack st1;
	st1.Push(1);
	st1.Push(2);
	Stack st2(10);
	st2.Push(10);
	st2.Push(20);
	st2.Push(30);
	st2.Push(40);
	st1 = st2;
}
int main()
{
	TestStack();
	return 0;
}

在这里插入图片描述
在这里插入图片描述
我们可以发现这里st2指针指向的内存地址是不是改变了啊

是不是实际上造成了内存泄漏(st2指针指向的地址释放不了)

和多次释放的问题(st1指针指向的地址多次释放 )

所以说系统的默认赋值重载并不能满足我们的需要

这里我们应该自己再写一个

在这里插入图片描述
我们来看看结果

在这里插入图片描述
这里要注意一点 我们返回栈一定要引用返回

不然的话就会引起拷贝构造 使用完毕之后会析构 导致我们st1里里面指针指向的空间被释放

而在程序结束之后会二次(析构)释放 所以说会报错

4.5 赋值重载的总结

  1. 参数尽量使用引用传参 提高效率
  2. 返回值尽量使用引用返回 为了提高效率和连续赋值
  3. 要检查是否自己给自己赋值 加个if判断就好 如果自己给自己赋值就是无意义的 所以说直接break;
  4. 返回值要返回*this (其实就是返回当前类)

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

这个很好理解 你要是重载全局函数不就乱套了嘛?

当用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值

注意:如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必须要实现

上面有很多的例子说明了

总结

在这里插入图片描述

本篇博客主要带领大家学习了四种重要的默认函数
其中构造函数和析构函数是一对 一个初始化 一个销毁
构造函数跟拷贝函数很像 区别在于拷贝函数多了一个引用参数
赋值重载函数的注意点很多 总结起来需要内存管理的函数要特别注意

以上就是本篇博客的全部内容啦
由于博主才疏学浅所以难免会出现错误 希望大佬可以及时指正
如果本篇博客帮助到你的话别忘了一件三连啊
阿尼亚 哇酷哇酷!

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

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

相关文章

破解系统密码与重装windows系统

数据来源 一、利用5次shift漏洞破解win7密码 1.1 漏洞 1. 在未登录时&#xff0c;连续按5次shift键&#xff0c;弹出程序C:\Windows\System32\sethc.exe 2. 部分win7及win10系统在未进入系统时&#xff0c;可以通过系统修复漏洞篡改系统文件名&#xff01; 注意&#xff1a;…

使用Maven部署到远程Linux服务器Tomcat

一、安装JDK 首先给服务器安装jdk&#xff0c;访问官网下载&#xff1a;Java Downloads | Oracle&#xff0c;下载图中的版本。首先我使用的是tomcat10&#xff0c;最低支持jdk1.8。安装了jdk19&#xff0c;是当时的最新版实测tomcat开启失败&#xff0c;新版jdk也不自带jre&a…

Windows上使用QEMU创建aarch64(ARM64)虚拟机

前言 随着国产化的推进&#xff0c;现在采用ARM、MIPS的机器越来越多&#xff0c;作为开发、运维人员要调测软件总不能每种架构的机器都去买一台吧&#xff1f;主要像博主这样的穷B&#xff0c;实在也是承受不起。。 需要的工具 1、QEMU Windows版官网下载地址&#xff1a;…

软件测试最最最重要的事

软件测试用例得出软件测试用例的内容&#xff0c;其次&#xff0c;按照软件测试写作方法&#xff0c;落实到文档中&#xff0c;两者是形式和内容的关系&#xff0c;好的测试用例不仅方便自己和别人查看&#xff0c;而且能帮助设计的时候考虑的更周。 一个好的测试用例必须包含…

Articulate360在线学习课件制作工具

Articulate是一款全新理念的在线和移动学习课件制作工具&#xff0c;可以说是目前国际上用户最广泛的e-learning课件制作工具之一。它包含了全新版的Storyline 360和Rise 360以及大量其他创作应用程序。使用Storyline 360开发可在所有设备上运行的自定义交互式课程&#xff0c;…

Java日志框架的发展历史,你不想了解一下吗

前言 相信大家在项目开发中肯定遇到过log4j&#xff0c;JUL&#xff0c;slf4j&#xff0c;logback&#xff0c;log4j2等日志框架相关名词&#xff0c;这些日志框架之间到底有什么关系&#xff0c;Java日志框架究竟经历了什么样的发展历程&#xff0c;相信有很多人都对此充满了好…

Socket 编程基础

文章目录一、socket 简介二、socket 编程接口介绍1. socket()函数2. bind()函数3. listen()函数4. accept()函数5. connect()函数6. 发送和接收函数read()函数recv()函数write()函数send()函数7. close()关闭套接字三、IP 地址格式转换函数inet_pton()函数inet_ntop()函数本篇会…

决策树与随机森林在分类预测中的应用(附源码)

写在前面 今天给大家分享一下基于决策树和随机森林在乳腺癌分类中实战。决策树和随机森林是白盒模型&#xff0c;数学建模中常用到这两种模型&#xff0c;用于预测或分类&#xff0c;随机森林还可以进行特征选择&#xff0c;故很推荐大家学习&#xff01;&#xff01;&#xff…

Qt5.14.2在Windows下使用mysql

第一步:下载依赖 1.1去Qt官方下载Qt5.14.2的源代码: Index of /archive/qt/5.14/5.14.2/singlehttps://download.qt.io/archive/qt/5.14/5.14.2/single/ 下载链接:https://download.qt.io/archive/qt/5.14/5.14.2/single/qt-everywhere-src-5.14.2.zip 1.2去Mysql官网下载Mys…

面试官:说说TCP如何实现可靠传输

今天来讲一下TCP是如何保证可靠传输的。这也是面试常问的一个题目&#xff0c;这个问题不单止能看出你是否真的了解TCP原理&#xff0c;更看出你是否有一个总结的能力。 我们从三个部分来讲TCP是如何实现可靠传输的。 滑动窗口 首先是讲TCP中的滑动窗口&#xff0c;它和TCP的…

基本的Dos命令

基本的Dos命令 打开CMD的方式 开始系统命令提示符win键R输入cmd (推荐使用)在任意的文件夹下&#xff0c;按住Shift键鼠标右击&#xff0c;打开命令行窗口在资源管理器地址栏路径前面加 “cmd ”管理员运行方式&#xff1a;命令提示符右键以管理员身份运行&#xff08;最高权…

动态规划--01背包问题详解

代码随想录day42和day43 动态规划 模块01背包问题 “即使到不了远方&#xff0c;心中也要有远方的模样。” 文章目录1. 01背包理论基础1.1什么是背包问题1.2二维dp数组01背包1.3一维dp数组(滚动数组)01背包2.leetcode 416.分割等和子集2.1 详细思路及思考难点2.2具体步骤及代码…

当食品制造业遇见数字化工具,如何借助S2B2C电商系统实现企业新增长

食品制造业是我国产业发展中的重要组成部分&#xff0c;具有点多、面广、投资小、见效快的特点&#xff0c;在经济发展中发挥着重要作用。根据工信部数据统计&#xff0c;从2018至2021年我国食品制造业经营规模稳步增长&#xff0c;2021年我国食品制造业营业收入达21268.1亿元&…

QT·移植Qt到ARM平台及搭建Qt交叉编译环境

目录 一、编译tslib库 二、移植 tslib 到文件系统 三、编译Qt源码&#xff08;用于移植到ARM&#xff09; 四、移植Qt到文件系统 五、搭建 Qt Creator 交叉编译环境 六、获得Qt可执行文件的另一种方法 要想在ARM平台上运行Qt程序&#xff0c;得满足以下两个点&#xff1a;1、…

【表达式求值】

目录&#xff1a;前言一、有效的括号&#xff08;一&#xff09;题目分析&#xff08;二&#xff09;整体代码二、表达式求值&#xff08;一&#xff09;题目分析1.栈的基本操作&#xff1a;2. 大体思路&#xff1a;3.具体计算过程&#xff1a;&#xff08;二&#xff09;整体代…

【代码随想录】二刷-哈希表

哈希表 《代码随想录》 哈希表一般用来快速查找某个元素是否在一个集合中。如果使用枚举的话时间复杂度为O(n)&#xff0c;而使用哈希表只O(1)就可以做到。——元素查询。 242.有效的字母异位词 使用unordered_map // 时间复杂度 O(n) // 空间复杂度 O(n) class Solution { pub…

嵌入式分享合集94

一、单片机硬件电路设计 减少后级电源对前级的影响&#xff0c;防止电源正负接反烧坏后级电路&#xff0c;防止电源关电时电流倒灌&#xff0c;但经过二极管有0.4V左右压降&#xff0c;需要考虑经过0.4V降压后会不会低于后级电路的正常工作电压。 一、按键电路 R1上拉电阻&…

用C语言开发入门游戏FlappyBird

前言 《flappy bird》是一款由来自越南的独立游戏开发者Dong Nguyen所开发的作品&#xff0c;游戏于2013年5月24日上线&#xff0c;并在2014年2月突然暴红。2014年2月&#xff0c;《Flappy Bird》被开发者本人从苹果及谷歌应用商店撤下。2014年8月份正式回归APP Store&#xf…

java从零开始系统性学习完整笔记(一)

java从零开始系统性学习完整超全资源笔记(还在更新中&#xff09; 前言 资源来自&#xff1a;王汉远java基础&#xff0c; B站视频&#xff1a; https://www.bilibili.com/video/BV1b4411g7bj/?spm_id_from333.1007.top_right_bar_window_custom_collection.content.click&a…

渗透测试之分享常用工具、插件和脚本(干货)

BRUP插件&#xff1a; 漏洞挖掘插件&#xff1a;Autorize、CSRF Token Tracker、XSS Validator、Turbo Intruder 辅助插件&#xff1a;HaE、sqlmap4brup、hackbar、Software Vulnerability Scanner 浏览器插件&#xff1a; wappalyzer、MySSL、Cookie Editor 脚本&#xff1a; …