【C++】——类和对象(中)

news2025/2/24 10:06:56

 一、前言

        好久没有更新内容了,今天为大家带来类和对形中期的内容 !

二、正文

1.this指针

1.1this指针的引入

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, d2;
	d1.Init(2023,5,12);
	d2.Init(2023,5,13);
	d1.Print();
	d2.Print();

}

        在看完上面关于“日期”这个类的定义后,不知道小伙伴是否有着这样一个疑惑?

        Date类中有Init与Print两个成员函数,函数体中没有关于不同对象的区分,那么当d1调用Init函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?

        在C语言中当我们在实现这样的功能的时候是我们自己手动要传对象的指针给函数的,而C++是引入this指针来解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参 数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

1.2this指针的特性

        在引入了this指针后,我们就来了解下this指针到底有哪些特性呢?

①this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。

②只能在“成员函数”的内部使用

③this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。 所以对象中不存储this指针

④ this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

//看到的
void Print()
{
	cout << _year << "-" << _month << "-" << _day << endl;
}

//实际上[编译器自动处理]
void Print(Date*this)
{
	cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
}

 2.类的六个默认成员函数

        如果一个类中什么成员都没有,简称为空类。

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

 

3.构造函数

3.1概念

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(2023,5,12);
	d1.Print();

	Date d2;
	d2.Init(2023, 5, 13);
	d2.Print();
}

        对于Date类,可以通过 Init 公有方法给对象设置日期,但如果每次创建对象时都调用该方法设置信息,未免有点麻烦,况且有时候还可能会忘记初始化,那能否在对象创建时,就将信息设置进去呢?因此就有了构造函数的存在。

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

3.2特性

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

其特征如下:

①函数名与类名相同

②无返回值

③对象实例化时编译器自动调用相应的构造函数

④构造函数可以重载

⑤如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。

⑥对于自定类型成员会调用它的默认成员函数,而对于内置类型,在不同的编译器下会有不同的处理方式

⑦无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。

注:C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时 可以给默认值。

class Time
{
public:
	Time()
	{
		cout << "Time()" << endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}

private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{

public:
	//1.无参构造函数
	Date()
	{}
	//2.带参构造函数
	Date(int year, int month, int day)
	{
		int _year; 
		int _month;
		int _day;  
	}
private:
	//基本类型(内置类型)——可以给默认值
	int _year=2023;
	int _month=5;
	int _day=13;

	//自定义类型——编译器生成的默认构造函数会自动调用 _t的构造函数
	Time _t;
};

void TestDate()
{
	Date d1; //调用无参构造函数
	Date d2(2015, 1, 1); //调用带参数的构造函数
	
	//注:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
	//例:Date d3();
}

3.3应用场景

        那么什么时候需要我们自己书写构造函数呢?

       一般情况下,构造函数都需要我们自己写,而以下两种情况下可以考虑不用写:

①内置类型成员都有缺省值,且初始化符合我们的要求

②全是自定义类型的构造,且这些类型都定义了默认构造函数

4、析构函数

4.1概念

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

        析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成 的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

 4.2特性

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

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

②无参数无返回值类型。

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

④ 对象生命周期结束时,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);
}

4.3应用场景

        在了解完析构函数之后,可能有的小伙伴会问那我们什么时候该自己写析构函数,什么时候写析构函数呢?

        在一般情况下下,有动态申请资源就需要写析构函数释放资源,比如malloc了一块内存空间等,而没有动态申请的资源或者需要释放资源的成员都是自定义类型,就不需要写析构函数了

5.拷贝构造函数

 5.1概念

        在日常的生活中,我们常常可能会见到两个一模一样的物品,比如:水杯,足球……那么我们在创建对象的时候,能不能创建一个与已存在对象一样的新对象呢?答案是肯定的。

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

5.2特征

拷贝构造函数也是特殊的成员函数,其特征如下:

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

2.拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷

递归调用

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

	//错误写法
	Date( Date d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

   我们会发现正确的拷贝构造相比于错误写法有两个不同的地方:1.引用 2.const

    前者是为了避免调用拷贝构造函数出现无穷递归,当然编译器也会进行检查,后者是为了避免我们书写时容易出现将要被拷贝的对象与拷贝对象写反,导致二者的成员都为随机值的现象

        3.若未显式定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝

        换句话来说:内置类型成员完成值拷贝/浅拷贝;自定义类型成员会调用它的拷贝构造函数

#include <iostream>
using namespace std;

class Date
{
public:
	Date(int year=0,int month=0,int day=0)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	拷贝构造函数
	//Date(const Date& d)
	//{
	//	_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(2024, 1, 23);
	Date d2(d1);
	d2.print();
}

         当我们将我们前文自己写过的拷贝构造函数注释掉后,我们会发现结果是一样的,这就是编译器自己生成的默认构造函数的效果

 

         4.编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝,那么还需要我们自己显式实现吗?虽然像上面的日期类对象无需我们显式实现,但是并不是所有的类都适用的,比如说下面这种情况

typedef int DataType;
class Stack
{
public:
	Stack(size_t capacity = 10)
	{
		_array = (DataType*)malloc(capacity * sizeof(DataType));
		_size = 0;
		_capacity = capacity;
	}
	void Push(const DataType& data)
	{
		//checkCaapacity();  //检查容量
		_array[_size++] = data;
	}

	~Stack()
	{
		if (_array)
		{
			free(_array);
			_capacity = _size = 0;
		}
	}
private:
	DataType* _array;
	size_t _size;
	size_t _capacity;
};

void Text2()
{
	Stack st1=Stack(10);
	st1.Push(1);
	st1.Push(2);
	Stack st2(st1);
}

int main()
{
	Text2();
}

         对于上述对象,当我不显式实现,而只依赖于编译器自己生成的默认构造函数后,我们会发现拷贝后的对象st2的大小,容量和内容与st1都是一样的,但是同时我们发现两者的成员_array的地址是一样,那么当函数结束的时候,st1与st2都会调用它们各自的析构函数,这时候_array所指向空间就被释放了两次,于是就出现了问题。

        由此这也是为什么编译器能够自己生成默认的拷贝构造函数后,有时候我们还需要显示实现拷贝函数。因为前者只能实现值拷贝/浅拷贝,而一旦涉及内存等,简简单单的拷贝就不能够满足了。这时候我们就要实现深拷贝了,后面也会详细讲解

 

6.赋值运算符重载

6.1 运算符重载

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

        函数名字:关键字“operator”+重载的运算符符号  eg:operator ==

        函数原型:返回值类型 operator操作符(参数列表)eg:Data operator+(int day)

注意:

●不能通过连接其他符号来创建新的操作符:比如说operator@

●重载操作符必须有一个类类型参数

●用于内置类型的运算符。其含义不能改变,例如:内置的整型+,不能改变其含义

●作为类成员函数重载时,其形参看起来比操作数目少1,因为成员函数的第一个参数为隐藏的this指针

●“.*”, “: :”, “sizeof”, “?:” , “.”,注意以上5个运算符不能重载

 6.2赋值运算符重载

1.赋值运算符重载格式

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

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

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

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

//赋值运算符重载
	Data& operator=(const Data& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;
	}

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

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

3. 由第2点我们知道,当用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝、

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

class Time
{
public:
	Time()
	{
		_hour = 1;
		_minute = 1;
		_second = 1;
	}
	Time& operator=(const Time& t)
	{
		if (this != &t)
		{
			_hour = t._hour;
			_minute = t._minute;
			_second = t._second;
		}
		return *this;
	}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
private:
	// 基本类型(内置类型)
	int _year = 2024;
	int _month = 1;
	int _day = 25;
	// 自定义类型
	Time _t;
};

int main()
{
	Date d1;
	Date d2;
	d1 = d2;
	return 0;
}

         与上面讲过的默认构造函数类似,虽然编译器生成的默认赋值构造函数虽然可以完成值拷贝/浅拷贝,但是对于Stack这样涉及资源管理类仅靠简单拷贝是不行的,也是需要我们去实现深拷贝

6.3前置++与后置++重载 

        对于前置++与后置++两个函数我们知道前者是先++再使用,而后者是先试用再++,那么对于编译器而言它该如何区别呢,于是我们便在传参中进行变化,如果传参数便是后置++,无则是前置,当然这是编译器的区分。在实际的使用中我们无需传参数,只要像内置类型一样便可以。

	Data& operator++()
	{
		*this += 1;
		return *this;
	}

	Data operator++(int)
	{
		Data tmp = (*this);
		++(*this);
		return tmp;
	}

    int main()
    {
        Data d1;
        d1++;
        ++d1
    }

7.日期类的实现

         在掌握了前面的有关类的知识后,我们就可以简单的写一个类了。

        下面以日期类的实现为例

typedef int DataType;

class Data
{
public:
	//构造函数
	Data(DataType year=0,DataType month=0,DataType day=0)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//拷贝构造函数
	Data(const Data& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	//赋值运算符重载
	Data& operator=(const Data& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;
	}
	//>运算符重载
	bool operator>(const Data& d)
	{
		if (_year > d._year)
			return true;
		else if (_year == d._year && _month > d._month)
			return true;
		else if (_month == d._month && _day > d._day)
			return true;
		else return false;
	}
	//==运算符重载
	bool operator ==(const Data& d)
	{
		if (_year == d._year && _month == d._month && _day == d._day)
			return true;
		else
			return false;
	}
	///>=运算符重载
	bool operator >=(const Data& d)
	{
		return(((*this) > d) || ((*this) == d));
	}
	//<运算符重载
	bool operator <(const Data& d)
	{
		return !(*this>=d);
	}
	//<=运算符重载
	bool operator <=(const Data& d)
	{
		return !(*this >d);
	}
	//获取指定年月的天数
	 static DataType GetMonthDay(DataType year,DataType month)
	{
		 DataType days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		 //判断闰年
		 if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		 {
			 return days[2] + 1;
		 }
		 else
			 return days[month];

	}
	 //+=运算符重载    日期+=天数
	 Data& operator+=(DataType day)
	 {
		 if (day > 0)
		 {
			 _day += day;
			 while (_day > GetMonthDay(_year, _month))
			 {
				 _day -= GetMonthDay(_year, _month);
				 _month++;
				 if (_month > 12)
				 {
					 _month = 1;
					 _year += 1;
				 }
			 }
			 return *this;
		 }
		 else
			 *this -= (-day);
		
	 }

	 //+运算符重载    日期+天数
	 Data operator+(DataType day)
	 {
		 Data tem(*this);
		 tem += day;
		 return tem;
	 }
	 //前置++运算符重载    
	Data& operator++()
	{
		*this += 1;
		return *this;
	}
	//后置++运算符重载    
	Data operator++(int)
	{
		Data tmp = (*this);
		++(*this);
		return tmp;
	}
	//日期的打印
	 void print()
	{
		cout << _year << '-' << _month <<'-'  << _day << endl;
	}
	 //-=运算符重载    日期-=天数
	 Data& operator-=(DataType day)
	 {
		 if (day > 0)
		 {
			 _day -= day;
			 while (_day <= 0)
			 {
				 _month -= 1;

				 if (_month == 0)
				 {
					 _month = 12;
					 _year -= 1;
				 }
				 _day += GetMonthDay(_year, _month);
			 }
			 return *this;

		 }
		 else
			 *this += (-day);
	 }
	 //-运算符重载    日期-天数

	 Data operator-(DataType day)
	 {
		 Data tem(*this);
		 tem -= day;
		 return tem;
	 }
	 //前置--运算符重载

	 Data& operator--()
	 {
		 *this -= 1;
		 return *this;
	 }
	 //-后置-运算符重载

	 Data operator--(int)
	 {
		 Data tmp = (*this);
		 --(*this);
		 return tmp;
	 }
     //日期-日期
	 DataType operator-(const Data& d)
	 {
		 Data tmp = *this;
		 int dis = 0; //天数差值
		 if (tmp >d)
		 {
			 while (tmp > d)
			 {
				 --(tmp);
				 dis++;
			 }
		 }
		 else if(tmp < d)
		 {
			 while (tmp< d)
			 {
				 ++(tmp);
				 --dis;
			 }
		 }
		 return dis;
	}

private:
	DataType _year;
	DataType _month;
	DataType _day;


};

8.const成员

         将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改,也就是只读不写

 void print() const

	{
		cout << _year << '-' << _month <<'-'  << _day << endl;
	}

9.取地址及const取地址操作符重载

        这两个默认成员函数一般不用重新定义,编译器会默认生成。

        而且一般需要重载,使用编译器默认取地址的重载即可,只有特殊情况,才需要 重载,比如想让别人获取到指定的内容

class Date
{
 public :
     Date* operator&()
     {
         return this ;
     }

     const Date* operator&()const
     {
         return this ;
     }
private :
     int _year ; // 年
     int _month ; // 月
     int _day ; // 日
};

 

 

 

 

 

 

 

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

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

相关文章

2. HarmonyOS 应用开发 DevEco Studio 准备-2

2. HarmonyOS 应用开发 DevEco Studio 准备-2 首选项设置 中文设置 主题 字体 插件安装和使用 保存时操作 编辑器 工程树管理 代码树管理 标记 字符串可视化编辑 参考文档 常用快捷键 编辑 查找或替换 编译与运行 调试 其他 预览 页面预览 自定义组件预览 预览…

2023年中国工控自动化市场现状及竞争分析,美日占主角,国产品牌初崭头角

工控自动化是一种运用控制理论、仪器仪表理论、计算机和信息技术&#xff0c;对工业生产过程实现检测、控制、优化、调度、管理和决策&#xff0c;达到增加产量、提高质量、降低消耗、确保安全等目的综合性技术。产品应用领域广泛&#xff0c;可分为OEM型行业和项目型行业。 近…

Metaphor(EXA) 基于大语言模型的搜索引擎

文章目录 关于 Metaphor使用示例 关于 Metaphor Metaphor是基于大语言模型的搜索引擎&#xff0c;允许用户使用完整的句子和自然语言搜索&#xff0c;还可以模拟人们在互联网上分享和谈论链接的方式进行查询内容。 Metaphor同时还能与LLMs结合使用&#xff0c;允许LLMs连接互联…

༺༽༾ཊ—Unity之-05-抽象工厂模式—ཏ༿༼༻

首先创建一个项目&#xff0c; 在这个初始界面我们需要做一些准备工作&#xff0c; 建基础通用文件夹&#xff0c; 创建一个Plane 重置后 缩放100倍 加一个颜色&#xff0c; 任务&#xff1a;使用 抽象工厂模式 创建 人物与宠物 模型&#xff0c; 首先资源商店下载 人物与宠物…

【JavaWeb】【C00153】基于SSM的大学生家教平台管理系统(论文+PPT)

基于SSM的大学生家教平台管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm大学生家教平台管理系统 本系统分为前台模块、后台管理员模块、用户木块及家教模块。 其中前台的权限为&#xff1a;首页、家教、公告信息…

猫用空气净化器哪款牌子好?好用能吸毛的宠物空气净化器推荐

作为一个养猫多年的铲屎官&#xff0c;我真的无法抗拒猫星人的可爱魅力&#xff01;以前&#xff0c;每当我路过宠物店&#xff0c;我总会忍不住停下来&#xff0c;在玻璃窗前停留半个小时以上。但是后来&#xff0c;我终于有了自己的猫咪。每天都能享受到给它摸小肚子的乐趣&a…

Filter Listener

文章目录 一 过滤器&#xff08;Filter&#xff09;1 什么是过滤器2 为什么使用过滤器3 过滤器执行流程4 过滤器的生命周期5 过滤器的注册5.1 XML方式5.2 WebFilter 注解方式 6 FilterConfig7 过滤器链8 过滤器应用 二 什么是监听器1 监听器分类2 监听器使用2.1 监听对象的创建…

Mac忘记本机MySql怎么办?

Mac忘记本机MySql怎么办&#xff1f; 1.打开系统偏好设置 2.打开Mysql 3.停止服务 4.直接初始化服务上图有一个初始化数据库 5.输入8位密码确认 6.重启服务

Blender教程(基础)-初始用户界面-01

开始第一天的Blender学习、也是业余学习。希望记录下这一份学习的过程、并且分享给大家。今天带大家认识Blender这一款软件&#xff0c;先说说我为什么选择了Blender&#xff0c;我在软件市场找了好久&#xff0c;市场上其他雷同软件都是要么收费要么不好用&#xff0c;最终决定…

【面试深度解析】滴滴后端二面:12306场景设计、Redis缓存设计、MyBatis两级缓存(下)

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

Mac安装nvm,安装多个不同版本node,指定node版本

一.安装nvm brew install nvm二。配置文件 touch ~/.zshrc echo export NVM_DIR~/.nvm >> ~/.zshrc echo source $(brew --prefix nvm)/nvm.sh >> ~/.zshrc三.查看安装版本 nvm -vnvm常用命令如下&#xff1a;nvm ls &#xff1a;列出所有已安装的 node 版本nvm…

一张图文深入了解信息量概念

通信原理第10页最后一段&#xff1a; 概率论告诉我们&#xff0c;事件的不确定程度可以用其出现的概率来描述。因此&#xff0c;消息中包含的信息量与消息发生的概率密切相关。消息出现的概率越小&#xff0c;则消息中包含的信息量就越大。 这句话怎么理解呢&#xff1f; 比如…

小红构造数组-牛客周赛 Round 29(DFS方法)

题目很直白&#xff0c;方法就是暴力即可。 虽然说数据范围显得很大&#xff0c;但是在长整型范围内&#xff0c;一个数字的素因子数量最多不超64&#xff0c;而如果是不相同的素因子&#xff0c;虽然没有计算过&#xff0c;但是如果是12个不同的素因子应该会超过数据范围了。…

消息中间件之八股面试回答篇:三、RabbitMQ如何解决消息堆积问题(100万条消息堆积)+RabbitMQ高可用性和强一致性机制+回答模板

RabbitMQ中的消息堆积问题 当生产者发送消息的速度超过了消费者处理消息的速度&#xff0c;就会导致队列中的消息堆积&#xff0c;直到队列存储消息达到上限。之后发送的消息就会成为死信&#xff0c;可能会被丢弃&#xff0c;这就是消息堆积问题。 解决消息堆积有三种种思路…

c++阶梯之引用与内联函数

1. 引用 1.1 引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 语法 类型& 引用变量名(对象名) 引用实体; 示例 很显然&#xff0c;在下面这…

21.Arrays类

Arrays类 1. 概述2. 常见方法3. sort 方法的自定义排序4. 代码示例5. 输出结果6. 注意事项 具体信息请查看 API 帮助文档 1. 概述 Arrays类是Java中的一个工具类&#xff0c;位于java.util包中。 它提供了一组静态方法&#xff0c;用于操作数组。通过Arrays类&#xff0c;我们…

springboot136人口老龄化社区服务与管理平台

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

web前端---------盒子模型2

一------内边距 padding 属性用来设置元素的内边距长度&#xff0c;元素在默认情况下没有内边距&#xff0c;其值为none。 &#xff08;1&#xff09;当 padding 属性中仅含一个值时&#xff0c;该长度应用在上、下、左、右四个区域。 &#xff08;2&#xff09;当 padding …

Java二分查找-图文

一、二分查找概念 二分查找也叫折半查找&#xff0c;是在一组有序(升序/降序)的数据中查找一个元素&#xff0c;它是一种效率较高的查找方。 二、二分查找原理 1.二分查找的数组必须是有序数值型数组。 2.将想要查找的目标元素与查找范围内的中间元素进行比较&#xff0c;如果…

文件包含漏洞长度截断

长度截断 文件漏洞的利用方式什么是长度截断通过实操理解00截断对版本要求更高一点&#xff0c;而长度截断则是利用了windows的系统漏洞&#xff0c;就是windows文件名&#xff08;就是文件名后缀之后&#xff09;之后如果有空格&#xff0c;或者是点都会被忽略掉&#xff0c;也…