【C++】类的6个默认成员函数

目录

1. 类的6个默认成员函数

2. 构造函数

3. 析构函数

4. 拷贝构造函数

5. 运算符重载

5.1运算符重载

5.2赋值运算符重载

 5.3前置++和后置++重载

5.4日期类的实现

6. const成员函数

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


1. 类的6个默认成员函数

对于一个空类,编译器会自动生成以下6个默认成员函数

2. 构造函数

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

构造函数的主要任务不是开空间创建对象而是初始化对象

构造函数的特性:

1️⃣函数名和类名相同

2️⃣无返回值

3️⃣对象实例化时编译器自动调用对应的构造函数

4️⃣构造函数可以重载

调用无参构造函数初始化对象时,对象后面不用跟括号,否则会和函数声明混淆;

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

编译器生成的默认构造函数:

在上面的日期类中,我们创建了一个对象,通过默认构造函数初始化后,_year,_month,_day中仍是随机值,那编译器生成的默认构造函数的意义是什么呢?

C++中把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如int、char等;自定义类型就是我们使用关键字class/struct/union等自己定义的类型。编译器生成的默认构造函数会对自定义类型成员调用它的默认构造函数,而内置类型不作处理,C++11中,针对内置类型成员不初始化的缺陷,打了补丁:内置类型成员变量在类声明时可以给默认值

定义如下一个类: 

class Time
{
public:Time(){cout << "调用构造函数Time()" << endl;_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};

在日期类中添加我们自定义类型的一个成员变量_time,调试可以发现,创建一个对象时,会调用自定义类型成员变量的构造函数,完成初始化。

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

实际上这种方式是给内置类型的成员变量一个缺省值

内置类型的成员变量初始化: 

6️⃣无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认的构造函数只能有一个,若存在多个,则调用时存在二义性。无参构造函数全缺省的构造函数编译器默认生成的构造函数,都可以认为是默认构造函数

默认构造函数不传参就可以调用的构造函数

3. 析构函数

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

析构函数的特性:

1️⃣析构函数名是在类名前加上~

2️⃣无参数无返回值类型,因此析构函数不支持重载

3️⃣一个类只能有一个析构函数,若未显式定义,则编译器会自动生成默认的析构函数

4️⃣对象的生命周期结束时,系统自动调用析构函数

5️⃣编译器生成的默认析构函数,对自定义类型成员调用它的析构函数

📖Note:

当创建的Date类对象销毁时,要保证其内部所有的成员都可以被销毁,test1函数中没有直接调用Time类的析构函数,而是调用Date类的析构函数(编译器自动生成的),Date类的析构函数中才会调用Time类的析构函数。

创建哪个类的对象则调用该类的构造函数,销毁哪个类的对象则调用该类的析构函数

6️⃣如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,需要自己写析构函数,否则会造成资源泄露,比如Stack类

4. 拷贝构造函数

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

拷贝构造函数的特性:

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

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

传值传参引发的无穷递归调用

函数调用时,形参是实参的一份临时拷贝,在传值传参的过程中,会产生一个临时中间变量,先将d1拷贝给这个临时变量,这次拷贝会调用拷贝构造函数,而拷贝构造函数的传传参方式是传值传参,所以每次调用拷贝构造都会产生临时变量,调用拷贝构造函数,因此引发了无穷的函数调用。传参过程如下图:

 

3️⃣若未显式定义,编译器会自动生成默认的拷贝构造函数。默认的拷贝构造函数对内置类型的成员变量按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝;对自定义类型的成员变量通过调用其拷贝构造函数完成拷贝

class Stack
{
public://构造函数Stack(size_t capacity = 10){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (nullptr == _array){perror("malloc failed");return;}_capacity = capacity;_top = 0;}//析构函数~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_top = 0;}}//压栈void Push(const DataType& data){//扩容CheckCapacity();_array[_top] = data;++_top;}private://扩容void CheckCapacity(){//栈满if (_top == _capacity){int newcapacity = _capacity * 2;DataType* tmp = (DataType*)realloc(_array, newcapacity * sizeof(DataType));if (tmp == NULL){perror("realloc failed\n");return;}_array = tmp;_capacity = newcapacity;}}
private://变量定义DataType* _array;size_t _capacity;size_t _top;
};

如上图,当我们没有显式定义拷贝构造函数,使用系统自动生成的拷贝构造函数时,对于栈类,一次拷贝构造后,栈s1和栈s2指向了同一块内存空间

程序退出时,栈s1和栈s2需要销毁,后定义变量的先销毁,即s2先销毁,调用析构函数,将这块内存空间释放,s2再销毁,调用析构函数,也要释放这块空间,但此时这块空间已经被释放了,因此程序会崩溃

以上过程是一次浅拷贝的过程;对于栈类,需要显式定义拷贝构造函数以实现深拷贝,即使用栈s1拷贝构造栈s2时,需要开辟和s1相同大小的空间,并将s1中的值拷贝过来,这样栈s1和栈s2都拥有自己的空间,二者相互独立,不影响后续的操作

📖Note:

类中如果没有涉及资源申请时,拷贝构造函数可以不显式定义,如日期类;一旦类中涉及资源申请,则一定要显式定义拷贝构造函数,否则拷贝就是浅拷贝,如栈

总结:需要写析构函数的类,都要显式定义深拷贝的拷贝构造函数,其他类使用默认生成的拷贝构造函数即可

4️⃣拷贝构造函数典型的调用场景

  • 使用已存在对象创建新对象(上述例子)
  • 函数参数类型为类类型对象
  • 函数返回值类型为类类型对象

总结:

为了提高程序效率,对象传参时尽量使用引用传参,返回时根据实际情况尽量使用引用返回

5. 运算符重载

5.1运算符重载

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

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

📖Note:

  1. 不能通过连接其他符号来创建新的操作符,如operator@
  2. 重载操作符必须有一个类类型参数
  3. 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
  4. 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this指针
  5. 不能重载的5个运算符:⑴ .*  、⑵ ::   、 ⑶sizeof  、⑷? :  、⑸​​​​​​​​​​​​​​ .

操作符==的重载 

全局的operator==存在的问题:私有的成员变量不能访问;如果将成员变量设置成公有的,则封装性不能保证

解决方案:

  1. 直接重载成成员函数
  2. 定义一个公有的成员函数GetYear(),获取私有的成员变量
  3. 使用友元

1️⃣直接重载成成员函数

此时形参列表中只需要显式定义一个参数,因为第一个参数为隐含的this指针

//日期类
class Date
{
public://操作符==重载bool operator==(const Date& d){return _year == d._year&& _month == d._month&& _day == d._day;}private:int _year;int _month;int _day;
};

2️⃣定义一个公有的成员函数GetYear(),获取私有的成员变量

注意获取成员函数的函数需要用const修饰

//日期类
class Date
{
public://获取私有成员函数int GetYear(const Date& d) const{return d._year;}int GetMonth(const Date& d) const{return d._month;}int GetDay(const Date& d) const{return d._day;}private:int _year;int _month;int _day;
};
//全局的operator==
bool operator==(const Date& d1,const Date& d2)
{return d1.GetYear(d1) == d2.GetYear(d2)&& d1.GetMonth(d1)== d2.GetMonth(d2)&& d1.GetDay(d1) == d2.GetDay(d2);
}int main()
{Date d1(2024, 2, 9);Date d2(2024, 2, 10);cout << (d1 == d2) << endl; //输出0return 0;
}

3️⃣使用友元

//日期类
class Date
{
public://全缺省的构造函数Date(int year = 2024, int month = 2, int day = 8){_year = year;_month = month;_day = day;}//拷贝构造Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//声明全局的operator==为友元函数friend bool operator==(const Date& d1, const Date& d2);private:int _year;int _month;int _day;
};
bool operator==(const Date& d1, const Date& d2)
{return d1._year == d2._year&& d1._month == d2._month&& d1._day == d2._day;
}

5.2赋值运算符重载

1️⃣赋值运算符重载格式:

  • 参数类型:const T&,引用传参可以提高传参效率(T表示数据类型)
  • 返回值类型:T&,引用返回可以提高返回的效率,有返回值的目的是为了支持连续赋值
  • 检测是否自己给自己赋值
  • 返回*this:要符合连续赋值的含义
//日期类
class Date
{
public://全缺省的构造函数Date(int year = 2024, int month = 2, int day = 8){_year = year;_month = month;_day = day;}//拷贝构造Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//赋值运算符重载Date& operator=(const Date& d){//避免自己给自己赋值if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}//打印void print(){cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;
};

赋值运算符重载:

参数列表中,只写了一个参数,实际上有两个参数,第一个参数是隐含的this指针,赋值操作符需要区分左右操作数,第一个参数是左操作数,第二个参数是右操作数

返回值:this指针是左操作数的地址,返回*this,即左操作数的值,除了赋值重载函数的作用域,左操作数这个对象还在,因此可以采用引用返回,避免一次拷贝构造,提高效率

返回值的类型是类类型,不需要加const,因为可能会对返回值做修改

 

连续赋值的情况:上述代码中,先执行d5 = d4,调用赋值重载,d5=d4转换为Date& operator (&d5,&d4),把d4的值拷贝给d5,并返回左操作数d5,因此d5 = d4这个表达式的值为d5,因此接下来执行的就是d6 = d5,即把d5的值拷贝给d6,和上述同样的操作,完成了一次连续赋值

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

赋值运算符如果在类内不显式实现,编译器会生成一个默认的赋值运算符重载。此时用户在类外实现的全局的赋值运算符重载会和编译器在类内生成的默认赋值运算符重载产生冲突,故赋值运算符重载只能是类的成员函数

3️⃣用户没有显式实现时,编译器会生成一个默认的的赋值运算符重载,以值的方式逐字节拷贝

📖Note:

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

栈的赋值重载:拷贝构造不能完成使用一个栈初始化另一个栈的操作,因为拷贝构造使两个栈指向了同一块空间,程序运行结束时析构两次会导致程序崩溃

当我们没有显式定义赋值运算符重载时,使用编译器在类内生成的默认赋值运算符重载,以值的方式逐字节拷贝每个成员变量的值,由上图,两个栈赋值时会发生错误

以值的方式逐字节拷贝,会导致栈s1和栈s2中的指针同时指向s2指向的空间,而原来s1指向的空间并没有释放,导致了内存泄漏;同时指向的这同一块空间会在程序结束时被析构两次

解决方案:在栈类内显式定义赋值运算符重载,为两个栈开辟不同的空间,使二者的结构独立

Stack& operator=(const Stack& st)
{if (this != &st){free(_array);//释放原来空间_array = (DataType*)malloc(sizeof(DataType) * st._capacity);if (_array == nullptr){perror("malloc failed");exit(-1);}memcpy(_array, st._array, sizeof(DataType) * st._top);_top = st._top;_capacity = st._capacity;}return *this;
}

if语句的作用是避免同一个栈自己给自己赋值

释放被赋值的对象原来空间后,开辟和右操作数对应的栈相同大小的空间,并将栈中的数据拷贝过去,就实现了两个栈独立存在

返回*this是为了可以实现连续的赋值操作

 5.3前置++和后置++重载

前置++:先++后使用 ===>返回值是++后的值

this指向的对象函数结束后不会销毁,因此可以使用引用返回

后置++:先使用后++ ===>返回值是++前的值

前置++和后置++都是一元运算符,为了使前置++和后置++能正确重载,C++规定:后置++运算符重载时多增加一个int类型的参数,但调用函数时该参数不用传递,由编译器自动传递。后置++要返回旧值,因此需要创建临时变量存储++前的值,最终返回的也是旧值,因为旧值存放在临时变量中,因此只能传值返回,不能引用返回

//日期类
class Date
{
public://构造函数Date(int year = 2024, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//打印void print(){cout << _year << "-" << _month << "-" << _day << endl;}//前置++Date& operator++(){_day += 1;return *this;}//后置++Date operator++(int){Date tmp(*this);//拷贝构造,存储++前的数据_day += 1;return tmp;}private:int _year;int _month;int _day;
};

📖Note:

对于后置++来说,它比前置++多了两次拷贝,一次调用拷贝构造,一次传值返回;因此对于自定义类型的变量,尽量使用前置++

前置--和后置--的实现和++类似

//前置--
Date& operator--()
{_day -= 1;return *this;
}//后置--
Date operator--(int)
{Date tmp(*this);//拷贝构造,存储++前的数据_day -= 1;return tmp;
}

5.4日期类的实现

//日期类
class Date
{
public:Date(int year = 2024, int month = 2, int day = 6){_year = year;_month = month;_day = day;//cout << "调用构造函数" << endl;}//拷贝构造函数Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;//cout << "调用拷贝构造函数" << endl;}//析构函数~Date(){//cout << "调用析构函数" << endl;}//打印void print() const{cout << _year << "-" << _month << "-" << _day << endl;}private://内置类型int _year = 1 ;int _month = 1;int _day = 1;
};

以上是一个简单的日期类,我们已经实现类赋值运算符的重载,操作符==的重载,以下我们将实现>、>=、<、<=、+、+=、-、-=等运算符的重载

 1️⃣>和>=的重载

//>的重载
bool operator>(const Date& d)
{if (_year > d._year){return true;}else if (_year == d._year && _month > d._month){return true;}else if (_year == d._year && _month == d._month && _day > d._day){return true;}return false;
}
//>=的重载
bool operator>=(const Date& d)
{return *this > d || *this == d;
}

2️⃣<和<=的重载

//<的重载
bool operator<(const Date& d)
{if (_year < d._year){return true;}else if (_year == d._year && _month < d._month){return true;}else if (_year == d._year && _month == d._month && _day < d._day){return true;}return false;
}
//<=的重载
bool operator<=(const Date& d)
{return *this < d || *this == d;
}

3️⃣+和+=的重载

日期类对象的假发涉及进位问题,因为存在大月小月,平年闰年问题,我们可以使用月份数组来获取某年某个月的天数

+=等重载可以引用返回,+的重载要返回临时变量中的值,只能传值返回

//月份数组
int GetMonthDay(int year, int month)
{int MonthDayArrary[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 29;}else{return MonthDayArrary[month];}
}
//+=的重载
Date& operator+=(int day)
{_day += day;//日期+day天//天数超出while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;//月份超出if (_month == 13){++_year;_month = 1;//年满之后,置1月份}}return *this;
}
//+的重载
Date operator+(int day)
{Date ret(*this);//拷贝构造ret += day;return ret;
}

4️⃣-和-=的重载:类似于+和+=,不够减则借位

//-=的重载
Date& operator-=(int day)
{_day -= day;//日期+day天//本月天数不够减,需要借位while (_day < 0){--_month;//本年月数不够减,需要借位if (_month == 0){--_year;_month = 12;//新的一年}_day += GetMonthDay(_year, _month);}return *this;
}
//-的重载
Date operator-(int day)
{Date ret(*this);//拷贝构造ret -= day;return ret;
}

+=、+、-、-=重载的完善:当某个日期加的天数是一个负数时,需要对这种情况进行处理,加一个负数就是减去这个负数的相反数(一个正数),调用减法的重载即可;当某个日期减的天数是一个负数时,相当于加去这个负数的相反数(一个正数),调用加法的重载即可;


//+=的重载
Date& operator+=(int day)
{//加一个负数===>减其相反数if (day < 0){return *this -= abs(day);}_day += day;//日期+day天//天数超出while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;//月份超出if (_month == 13){++_year;_month = 1;//年满之后,置1月份}}return *this;
}
//+的重载
Date operator+(int day)
{Date ret(*this);//拷贝构造//加一个负数===>减其相反数if (day < 0){ret -= abs(day);return ret;}ret += day;return ret;
}//-=的重载
Date& operator-=(int day)
{//减一个负数 ===>加其相反数if (day < 0){return *this += abs(day);}_day -= day;//日期+day天//本月天数不够减,需要借位while (_day < 0){--_month;//本年月数不够减,需要借位if (_month == 0){--_year;_month = 12;//新的一年}_day += GetMonthDay(_year, _month);}return *this;
}
//-的重载
Date operator-(int day)
{Date ret(*this);//拷贝构造//减一个负数 ===>加其相反数if (day < 0){ret += abs(day);return ret;}ret -= day;return ret;
}

6. const成员函数

const成员函数:将const修饰的成员函数称为const成员函数,const修饰类成员函数,实际修饰的是该成员函数隐含的this指针,表明该成员函数不能对类的任何成员进行修改

编译器对const成员函数的处理如下:

一些const修饰变量或函数时的权限问题:

以上代码属于const修饰时的权限放大问题:把一个使用const修饰的变量作为实参传递给一个没有const修饰的形参,编译器报错

以上代码中,成员函数使用const修饰后, this指针指向的对象为const Date类型的,因此实参指向的对象可以是const Date类型的,也可以是Date类型的,因为权限平移和权限缩小都是允许的

总结:

  1. const对象不可以调用非const成员函数(权限放大不允许)
  2. 非const对象可以调用const成员函数(权限缩小允许)
  3. const成员函数内不可以调用其他的非const成员函数(权限放大不允许)
  4. 非const成员函数内可以调用其他的const成员函数(权限缩小允许)

凡是内部不改变成员变量,也就是*this对象数据的,这些成员函数都应该加const修饰

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

这两个运算符一般不需要重载,使用编译器默认生成取地址的重载即可

//日期类
class Date
{
public://取地址重载Date* operator&(){return this;}//const修饰的取地址操作符重载,给const对象调用const Date* operator&() const{return this;}
private:int _year;int _month;int _day;
};

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

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

相关文章

JSDoc 真能取代 TypeScript?

这几个月&#xff0c;想必大家都听到过一个新闻&#xff1a; Svelte 弃用 TypeScript&#xff0c;改用 JSDoc 了。 TypeScript 我们知道&#xff0c;是用来给 JS 加上类型的&#xff0c;可以实现类型提示和编译时的类型检查。 那 JSDoc 能够完成一样的功能么&#xff1f;Svel…

图像处理常用算法—6个算子 !!

目录 前言 1、Sobel 算子 2、Isotropic Sobel 算子 3、Roberts 算子 4、Prewitt 算子 5、Laplacian算子 6、Canny算子 前言 同图像灰度不同&#xff0c;边界处一般会有明显的边缘&#xff0c;利用此特征可以分割图像。 需要说明的是&#xff1a;边缘和物体间的边界并不…

Android应用图标微技巧,8.0系统中应用图标的适配

大家好,2018年的第一篇文章到的稍微有点迟,也是因为在上一个Glide系列结束之后一直还没想到什么好的新题材。 现在已经进入了2018年,Android 8.0系统也逐渐开始普及起来了。三星今年推出的最新旗舰机Galaxy S9已经搭载了Android 8.0系统,紧接着小米、华为、OV等国产手机厂…

一句话总结Docker与K8S的关系

一句话总结&#xff1a;Docker只是容器的一种&#xff0c;它面向的是单体&#xff0c;K8S可以管理多种容器&#xff0c;它面向的是集群&#xff0c;Docker可以作为一种容器方案被K8S管理。下文继续具体介绍。 1、容器的核心概念 介绍这几个核心概念&#xff1a;OCI、CR、Runc、…

C语言指针运算

指针运算 指针加法意味着地址向上移动若干个目标指针减法意味着地址向下移动若干个目标示例&#xff1a; int a 100; int *p &a; // 指针 p 指向整型变量 aint *k1 p 2; // 向上移动 2 个目标&#xff08;2个int型数据&#xff09; int *k2 p - 3; // 向下移动 3 个…

PWM输入输出

PWM&#xff08;Pulse Width Modulation&#xff09;即脉冲宽度调制&#xff0c;在具有惯性的系统中&#xff0c;可以通过对一系列脉冲的宽度进行制&#xff0c;来等效地获得所需要的模拟参量&#xff0c;常应用于电机控速、开关电源等领域。 PWM参数 PWM 中有三个重要参数&…

寒假作业-day7

1>现有文件test.c\test1.c\main.c , 请编写Makefile. 代码&#xff1a; CCgcc EXEstr OBJS$(patsubst %.c,%.o,$(wildcard *.c)) CFLAGS-c -oall:$(EXE)$(EXE):$(OBJS)$(CC) $^ -o $%.o:%.c$(CC) $(CFLAGS) $ $^head.o:head.hclean:rm $(OBJS) $(EXE) 2>C编程实现&…

封装sku组件

1. 准备模板渲染规格数据 使用Vite快速创建一个Vue项目&#xff0c;在项目中添加请求插件axios&#xff0c;然后新增一个SKU组件&#xff0c;在根组件中把它渲染出来&#xff0c;下面是规格内容的基础模板 <script setup> import { onMounted, ref } from vue import axi…

NOVATEK显示技术系列之CEDSCHPI Training差异简介

CEDS的数据封包格式&#xff1a;首先CEDS数据封包包括三个部分&#xff1a; Training Pattern即Phase1Control Data 即 Phase2RGB Data 即Phase3 Power on Timing&#xff1a; 工作原理&#xff1a; Power ON时&#xff0c;TCON会发Training Pattern&#xff0c;当COF接受Tr…

江科大STM32 终

目录 SPI协议10.1 SPI简介W25Q64简介10.3 SPI软件读写W25Q6410.4 SPI硬件外设读写W25Q64 BKP备份寄存器、PER电源控制器、RTC实时时钟11.0 Unix时间戳代码示例&#xff1a;读写备份寄存器BKP11.2 RTC实时时钟 十二、PWR电源控制12.1 PWR简介代码示例&#xff1a;修改主频12.3 串…

分享90个行业PPT,总有一款适合您

分享90个行业PPT&#xff0c;总有一款适合您 90个行业PPT下载链接&#xff1a;https://pan.baidu.com/s/1bHvhk_42-IFAjNdjPPtMZw?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

题目描述 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 题目示例 输入&#xff1a;inorder [9,3,15,20,7], postorder [9,15,7,20,3] 输出&a…

B2078 含 k 个 3 的数(洛谷)

题目描述 输入两个正整数 m 和 k&#xff0c;其中 1<m≤&#xff0c;1<k≤15 &#xff0c;判断 m 是否恰好含有 k 个 3&#xff0c;如果满足条件&#xff0c;则输出 YES&#xff0c;否则&#xff0c;输出 NO。 输入格式 输入一行&#xff0c;为两个整数 m,k&#xff0…

揭开Markdown的秘籍:标题|文字样式|列表

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;Markdown指南、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️Markdown 标题二. ⛳️Markdown 文字样式2.1 &#x1f514;斜体2.2 &…

python智慧养老系统—养老信息服务平台vue

本论文中实现的智慧养老系统-养老信息服务平台将以管理员和用户的日常信息维护工作为主&#xff0c;主要涵盖了系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;养老资讯管理&#xff0c;养生有道管理&#xff0c;养老机构管理&#xff0c;系统管理等功能&#x…

海外云手机——平台引流的重要媒介

随着互联网的飞速发展&#xff0c;跨境电商、短视频引流以及游戏行业等领域正经历着迅猛的更新换代。在这个信息爆炸的时代&#xff0c;流量成为至关重要的资源&#xff0c;而其中引流环节更是关乎业务成功的关键。海外云手机崭露头角&#xff0c;成为这一传播过程中的重要媒介…

Ubuntu22.04 gnome-builder gnome C 应用程序习练笔记(一)

一、序言 gnome-builder构建器是gnome程序开发的集成环境&#xff0c;支持主力语言C, C, Vala, jscript, python等&#xff0c;界面以最新的 gtk 4.12 为主力&#xff0c;将其下版本的gtk直接压入了depreciated&#xff0c;但gtk4.12与普遍使用的gtk3有很大区别&#xff0c;原…

第6章 智能租房——前期准备

学习目标 了解智能租房项目&#xff0c;能够说出项目中各模块包含的功能 熟悉智能租房项目的开发模式与运行机制&#xff0c;能够复述项目的开发模式与运行机制 掌握智能租房项目的创建&#xff0c;能够独立创建智能租房项目 掌握智能租房项目的配置&#xff0c;能够为智能租…

排序算法---堆排序

原创不易&#xff0c;转载请注明出处。欢迎点赞收藏~ 堆排序&#xff08;Heap Sort&#xff09;是一种基于二叉堆数据结构的排序算法。它将待排序的元素构建成一个最大堆&#xff08;或最小堆&#xff09;&#xff0c;然后逐步将堆顶元素与堆的最后一个元素交换位置&#xff0c…

求职|基于Springboot的校园求职招聘系统设计与实现(源码+数据库+文档)

校园求职招聘系统目录 目录 基于Springboot的校园求职招聘系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、企业信息管理 3、公告类型管理 4、公告信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选…