C++类的六个默认成员函数(详细解析与总结)

news/2024/4/28 12:11:08/文章来源:https://blog.csdn.net/2301_79698419/article/details/137081278

目录

前言:

一、构造函数

a.特点

b.注意事项

1.首先明确什么是默认构造函数

2.默认构造函数对内置类型与自定义类型的处理

c.总结

二、析构函数

a.特点

b.注意事项

1.什么时候写析构函数?

2.析构函数对内置类型与自定义类型的处理

c.总结

三、拷贝构造

a.特点

b.特点的逐个分析以及注意事项

1.为什么拷贝构造要使用传引用返回?

2.为什么使用const修饰类类型对象的引用?

3.系统提供构造与拷贝构造的规则

4.拷贝构造对内置类型与自定义类型的处理

5.如果需要析构函数,则一般都需要拷贝构造与赋值重载

c.总结

四、运算符重载 

a.特点

b.实现日期类的比较

c.函数重载与运算符重载

d.总结

五、赋值重载

a.日期类实现赋值重载

b.赋值重载与拷贝构造

c.赋值重载对类型的处理

d.再来看流插入

e.日期类打印自定义类型

f.补充内联函数

g.总结

六、const修饰的非静态成员函数

七、const修饰的取地址操作符重载

总结:

本篇内容对六个默认成员函数进行了一个较为详细的分析,需要反复的复习并配合使用,其中构造,拷贝构造与运算符重载比较重要,在后面用的很多,后面还会有文章对这部分进行补充,例如友元函数和一些关键字。


 

前言:

本篇介绍的是有关于c++类中的六个默认成员函数(文章中附上了总结性的思维导图),为什么说是默认成员函数呢?因为大多数情况下,再一个类里面,如果没有写,编译器将会自动生成;如果写了某个,编译器将不会生成对应的默认成员函数;其次对于空类,六个默认成员函数不会生成,只会生成1byte的占位符。 


 

一、构造函数

a.特点

注意:
1.不用写返回值不代表返回值是void。

2.构造函数可重载说明一个类可以有多个构造函数。

3.第三条说明栈里面对象实例化需要初始化,可以在类里面用构造函数来初始化,再实例化对象就会自动调用初始化的构造函数了;无参的构造函数直接对对象实例化就自动调用;有参的构造函数在对象实例化时传参即可调用。

b.注意事项
1.首先明确什么是默认构造函数
class Date
{
public:private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{Date d1;return 0;
}

上面的代码是没自己写构造函数,所以可以直接调用编译器默认生成的,在对象实例化的时候自动初始化,注意自动生成的是无参的构造。

class Date
{
public://是默认构造Date()//无参的构造{_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day)//带参的构造{_year = year;_month = month;_day = day;}private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{//无参的构造调用不能这样写,编译器无法分明是函数声明还是构造函数Date();//去调用无参的默认构造Date d1;//带参函数构造调用Date d2(2024, 3, 27);return 0;
}

第一个构造为无参的构造,我们将它看为默认构造函数;第二个构造函数为带参的构造,不是默认的构造函数,需要显示的调用。

它们构成函数重载,需要注意的是,调用无参的构造不能直接写成Date(),这样编译器识别不出这是函数声明还是构造函数的调用。

class Date
{
public://是默认构造Date()//无参的构造{_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day)//带参的构造{_year = year;_month = month;_day = day;}//是默认构造Date(int year = 1, int month = 1, int day = 1)//将上方二者合而为一的全缺省的构造{_year = year;_month = month;_day = day;}private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{//无参的构造调用不能这样写,编译器无法分明是函数声明还是构造函数Date();//去调用默认构造Date d1;//带参函数构造调用Date d2(2024, 3, 27);return 0;
}

上面的第三个构造函数为全缺省的构造函数,将无参的与带参的构造函数结合到了一起,我们也认为它为默认构造函数。

但是需要考虑的是,全缺省的能和无参的一起使用吗???

答案是不能的,如果同时存在,那调用无参的构造函数应该去调用哪一个呢?会产生歧义,编译器会报对重载函数的调用不明确的错误;同样的,代码中第二个构造与第三个构造也不能同时存在,如果同时存在,那调用带参的构造函数时应该去调用谁呢?编译器会报构造函数已定义的错误。

2.默认构造函数对内置类型与自定义类型的处理

在我们调用默认生成的构造函数的时候,会发现,为什么用默认的构造函数初始化,对象中的成员变量为随机值,这有什么mao用???

这就关于我们默认成员函数的另一性质了,对于默认构造函数来说:

内置类型成员不做处理,自定义类型成员取调用它的默认构造(不用传参的构造)。

c++把类型分为内置类型(基本类型)与自定义类型:

内置类型:语言提供的类型,如int,char,double...以及这些类型的任意指针。

自定义类型:class,struct,union等自己定义的类型

后来c++11为了处理内置类型的初始化,增加了一条:

内置类型的声明位置可以给缺省值,注意不是初始化(因为给缺省值没有开空间),所以再对内置类型初始化时就不用给缺省值了(有些编译器会直接初始化为0,但是不要依赖)。 

c.总结

二、析构函数

a.特点

在对象销毁时会自动调用析构函数,完成对象中资源的清理工作。

b.注意事项
1.什么时候写析构函数?

析构函数什么时候写呢?像我们后面要完成的日期类可以不写析构函数,因为对象为局部变量,出了作用域就销毁了;而对于像栈的实现,有动态开辟的空间,在堆区上开辟空间,要写析构函数清理资源,否则会造成内存泄露,后面会举例说明。

2.析构函数对内置类型与自定义类型的处理

与构造函数一样,内置类型不做处理,自定义类型会调用它的析构函数。 

c.总结

三、拷贝构造

拷贝构造涉及内容比较深入,且注意点也很多,需要细细分析。

a.特点

b.特点的逐个分析以及注意事项
class Date
{
public:/*Date(){_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day){_year = year;_month = month;_day = day;}*/Date(int year = 12, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{//调用默认(全缺省)构造函数并使用函数中的缺省值Date d1;//调用默认(全缺省)构造函数并传参Date d2(2024, 3, 27);//调用拷贝构造Date d3(d2);//Date d3=d2;return 0;
}
1.为什么拷贝构造要使用传引用返回?

结合我们前面的知识,赋值其实就是拷贝(联想c++基础语法篇的隐式类型转换),对于类的对象来说,传值其实就是要去调用它的拷贝构造初始化,但是我们进行拷贝构造需要先传参,传参又是传值传参,传值传参又要调用拷贝构造......就陷入了死递归,且编译器会立刻报错。再根据我们之前c++语法讲解的使用传引用返回可以减少拷贝,所以我们在这里使用一个传引用返回就解决了这里的问题。(c++基础语法篇链接:http://t.csdnimg.cn/hCM1P)到这里有没有体会到知识融汇贯通的感觉呢?

2.为什么使用const修饰类类型对象的引用?

根据上面的代码,假设d2为const对象修饰的,我们在传参的时候传给类类型的引用d,此时d不是一个const修饰的引用,所以可以对其进行修改,这样我们就将权限放大了,而在任何时候权限只能缩小不能放大。

3.系统提供构造与拷贝构造的规则

搜先,由于拷贝构造是构造函数的重载,其实也就是构造的一种,所以我们如果自己写了拷贝构造,编译器就不会给我们提供任何默认的构造函数了,所以再想使用编译器生成的默认的无参构造函数初始化,就不行了,需要我们自己提供构造函数:

其次,如果我们提供了普通的有参的构造函数,且不是拷贝构造,那编译器将不再提供无参的默认构造,但是会提供拷贝构造(是浅拷贝),如下没有手写拷贝构造d3也能完成拷贝:

4.拷贝构造对内置类型与自定义类型的处理

对于拷贝构造而言,自定义类型的拷贝,需要调用拷贝构造;

内置类型可以直接拷贝,就像我们将d2拷贝给d3;或者需要深拷贝(默认生成的或者我们直接赋值的是浅拷贝,深拷贝需要我们自己写),因为拷贝是按字节去拷贝的,对于像动态开辟的变量,只是按字节拷贝,拷贝出来这两个动态变量在堆区上指向的位置却还是一样的,就像我们将栈的实现封装为stack这样的一个类,内置类型使用了动态开辟的变量,再进行拷贝,这样就会引发问题:

可以看到,拷贝出来的两个对象中的_a都指向了同一块空间(因为你只是负责拷贝字节,没法改变空间的指向啊),这样就会引发析构时需要析构两次,并且在这个场景下参与拷贝的两个对象插入删除数据会互相影响。

深拷贝:

再给st2开辟一块空间,再让st1按字节拷贝过去

以上是针对内置类型的深浅拷贝,下面是对于自定义类型的默认拷贝构造:

对于MYQueue这样的自定义类型,编译器默认生成的这三个构造函数的都可以用。

_size是内置类型,是值拷贝。

成员变量中的_pushST与_popST都是自定义类型(这里的stack没有封装成一个类,跟上面的stack不一样,这里是stack是自定义类型,会调用拷贝构造,但是这个自定义类型中有动态开辟的变量,所以要考虑深拷贝;而上面的stack是一个类,_a是它的成员,是一个内置类型,默认是浅拷贝(值拷贝),所以也需要考虑深拷贝。二者有些区别,注意区分),如果使用编译器默认生成的就是浅拷贝,因为它们都含有动态开辟的变量:

5.如果需要析构函数,则一般都需要拷贝构造与赋值重载

有了上面的知识,我们再来理解这句话就更加明白了,因为如果需要我们手写析构函数,一般来说是默认的析构函数不够用了,例如动态开辟的变量,所以为了防止刚刚提到的浅拷贝导致的双重释放,我们就要自己来写一个拷贝构造与赋值重载来防止浅拷贝。

c.总结

四、运算符重载 

下面要谈到赋值重载,就要先了解运算符重载。

a.特点

b.实现日期类的比较
class Date
{
public:/*Date(){_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day){_year = year;_month = month;_day = day;}*/Date(int year = 12, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//d1==d2bool operator==(const Date& d)//这里使用引用是因为函数传参也需要拷贝,引用来减少拷贝{return  _year == d._year//this->_year==d._year&& _month == d._month&& _day == d._day;}//d1<d2bool operator<(const Date& d){return (_year < d._year) ||((_year == d._year )&&( _month < d._month)) || ((_year == d._year) && (_month == d._month) &&( _day < d._day));}//d1<=d2bool operator<=(const Date& d){return (*this < d) || (*this == d);}//d1>d2bool operator>(const Date& d){return !(*this <= d);}//d1>=d2bool operator>=(const Date& d){return !(*this < d);}//d1!=d2bool operator!=(const Date& d){return !(*this == d);}private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{Date d1(2023, 3, 28);Date d2(2024, 3, 28);//调用时相当于d1.operator==(d2)//调用也可以写为operator==(d1,d2),但一般不会这样写cout<<(d1 == d2)<<endl;//0cout<<(d1 < d2)<<endl;//1cout<<(d1 > d2)<<endl;//0cout<<(d1 >= d2)<<endl;//0cout<<(d1 <= d2)<<endl;//1cout<<(d1 != d2)<<endl;//1//调用默认(全缺省)构造函数并使用函数中的缺省值//Date d1;//调用默认(全缺省)构造函数并传参//Date d2(2024, 3, 27);//调用拷贝构造//Date d3(d2);return 0;
}

注意使用时:

例如d1==d2,也可以写为operator==(d1,d2)(但是一般不会这样写),在调用的时候会转换为d1.operator==(d2),所以传的this指针也是第一个参数就是d1,第二个参数为d2。

这里比较返回bool值判断真假,在打印时需要注意,<<的优先级高于==等运算符,所以要加上括号。

进行比较的运算符的重载时,可以先写==与<或者其它的,然后其它的可以复用。

c.函数重载与运算符重载

运算符重载实际就是函数重载。

d.总结

五、赋值重载

我们来围绕日期类来进行举例说明,且下面的知识的梳理都是循序渐进的。

a.日期类实现赋值重载
class Date
{
public:/*Date(){_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day){_year = year;_month = month;_day = day;}*/Date(int year = 12, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//d1==d2bool operator==(const Date& d)//这里使用引用是因为函数传参也需要拷贝,引用来减少拷贝{return  _year == d._year//this->_year==d._year&& _month == d._month&& _day == d._day;}//d1<d2bool operator<(const Date& d){return (_year < d._year) ||((_year == d._year )&&( _month < d._month)) || ((_year == d._year) && (_month == d._month) &&( _day < d._day));}//d1<=d2bool operator<=(const Date& d){return (*this < d) || (*this == d);}//d1>d2bool operator>(const Date& d){return !(*this <= d);}//d1>=d2bool operator>=(const Date& d){return !(*this < d);}//d1!=d2bool operator!=(const Date& d){return !(*this == d);}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}private:int _year = 1;int _month = 1;int _day = 1;
};int main()
{Date d1(2023, 3, 28);Date d2(2024, 3, 28);Date d3(2025, 3, 28);//调用时相当于d1.operator==(d2)//调用也可以写为operator==(d1,d2),但一般不会这样写cout<<(d1 == d2)<<endl;//0cout<<(d1 < d2)<<endl;//1cout<<(d1 > d2)<<endl;//0cout<<(d1 >= d2)<<endl;//0cout<<(d1 <= d2)<<endl;//1cout<<(d1 != d2)<<endl;//1d3 = d1 = d2;d1.Print();d3.Print();//调用默认(全缺省)构造函数并使用函数中的缺省值//Date d1;//调用默认(全缺省)构造函数并传参//Date d2(2024, 3, 27);//调用拷贝构造//Date d3(d2);return 0;
}

注意:
 1.为什么要带返回值?

因为对于赋值运算符来说,例如i=j=k这个表达式,j=k这个表达式返回左操作数,返回值    再作为右操作数再赋值给给i。  

所以我们要支持连续赋值,例如d3=d1=d2,d1作为返回值对应*this,所以返回d1,那为什么要用*this呢?因为*this出了赋值重载的作用域还在(因为d1是在主函数定义的,生命周  期在主函数里)所以可以直接返回*this。

 2.为什么参数要用引用?

因为可以减少拷贝。当然这里不加&也不会死循环,因为传值传参调用拷贝构造,我们已经实现过拷贝构造了,调用完拷贝构造就进赋值重载函数了,只有自己对自己传值传参的拷贝构造才会死循环。

 3.为什么函数体要这样写?

函数中要考虑自己对自己赋值,判断一下防止自己对自己赋值。这里调用d1=d2也就是调用d1.operator=(d2)。

b.赋值重载与拷贝构造

注意区分赋值重载与拷贝构造,赋值重载是对于两个实例化的对象而言的。 

c.赋值重载对类型的处理

理解为与拷贝构造一样,也要考虑双重释放的问题。

d.再来看流插入

有了前面的知识储备,我们再来理解一下流插入与流提:

查阅官方文档,我们可以看到流插入也是经过了运算符的重载,而这个类就是我们库中的ostream这个类,运算符重载被封装在这个类里面了;而对于的我们使用cout,cin(cin是istream的对象)就是根据这个类创建的对象,然后去调用对应的运算符重载函数。

再进一步理解为什么我们使用c++中的流插入与流提取可以自动识别类型了,因为是在运算符重载中帮你实现好了:

上面的运算符重载都构成函数重载。假设我们现在有一个int类型的i与double类型的d,去使用流插入就是:

cout<<i;//cout.operator<<(i)   --->int
cout<<d;//cout.operator<<(d)  --->double

e.日期类打印自定义类型

结合前面的知识,我们知道了cout其实就是ostream的对象,现在我们来完成日期类的打印:

上面的可以完成吗?答案是不可以的,因为格式不符合我们的习惯:

调用的时候,由于第一个参数我们需要传递this指针,所以调用的时候写法只能如上图写。

那怎么办呢?我们不定义在类中不就好了:

 但是又发现,类中的保护起来的成员不让访问啊?那我们再让成员放开,有些不值当啊,所以我们可以有两种解决方案:

提供公有的成员函数来获取例如GetYear()等;或者提供一个友元函数(友元函数在类和对象的总结篇会细说):

注意位置放在类中公有和私有域的外面,这样我们的友元函数就能访问类中的成员了,此时调用就变为了:

现在完了吗?还没有!我们还需要考虑连续的调用(流插入从左往右连续调用),所以我们需要返回值,out是cout的别名,返回的其实就是cout:

完整代码:

class Date
{friend ostream& operator << (ostream& out, const Date& d);public:/*Date(){_year = 1;_month = 1;_day = 1;}Date(int year, int month, int day){_year = year;_month = month;_day = day;}*/Date(int year = 12, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//d1==d2bool operator==(const Date& d)//这里使用引用是因为函数传参也需要拷贝,引用来减少拷贝{return  _year == d._year//this->_year==d._year&& _month == d._month&& _day == d._day;}//d1<d2bool operator<(const Date& d){return (_year < d._year) ||((_year == d._year )&&( _month < d._month)) || ((_year == d._year) && (_month == d._month) &&( _day < d._day));}//d1<=d2bool operator<=(const Date& d){return (*this < d) || (*this == d);}//d1>d2bool operator>(const Date& d){return !(*this <= d);}//d1>=d2bool operator>=(const Date& d){return !(*this < d);}//d1!=d2bool operator!=(const Date& d){return !(*this == d);}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}private:int _year = 1;int _month = 1;int _day = 1;
};ostream& operator << (ostream & out, const Date & d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}int main()
{Date d1(2023, 3, 28);Date d2(2024, 3, 28);Date d3(2025, 3, 28);//调用时相当于d1.operator==(d2)//调用也可以写为operator==(d1,d2),但一般不会这样写cout<<(d1 == d2)<<endl;//0cout<<(d1 < d2)<<endl;//1cout<<(d1 > d2)<<endl;//0cout<<(d1 >= d2)<<endl;//0cout<<(d1 <= d2)<<endl;//1cout<<(d1 != d2)<<endl;//1d3 = d1 = d2;d1.Print();d3.Print();cout << d3;//调用默认(全缺省)构造函数并使用函数中的缺省值//Date d1;//调用默认(全缺省)构造函数并传参//Date d2(2024, 3, 27);//调用拷贝构造//Date d3(d2);return 0;
}

f.补充内联函数

如果我们在头文件中定义一个函数:

如果没有定义只有声明,那么就需要链接找到定义,call的时候没有地址,就需要到符号表里面去找函数的地址;如果有定义,再编译阶段就能拿到函数的地址,直接call地址就能找到这个函数。

而内联函数不会进符号表

所以我们在将内联函数定义到头文件时,要确保头文件中有定义和声明,这样在编译的阶段就能拿到函数的地址。不然没有定义需要去链接call内联函数的地址,就要去符号表找函数的地址,但是是找不到的。

g.总结

六、const修饰的非静态成员函数

 调用Print这里传递的还有&aa给this指针,而&aa的类型是const A*,传递给Print()后,变成了A* this,权限被放大了,但*this又不能改变,所以如图const写后面表示const修饰*this,this类型变成了const A*,不这样写编译器会报错。类内部不改变成员变量的成员函数,最好加上const(声明定义分离的都要加),const对象和普通对象都能调用。

 

通常间接的调用需要注意要加上const防止权限放大。Print中的this指针是个const A*类型的,用法Func的x去调用要确保x是一个const A类型的,防止权限放大。

 

七、const修饰的取地址操作符重载

一般不需要重载,使用编译器默认生成的即可。

也可写:

需要注意的是,不能加任何参数,不然就是被看做按位与&的重载了。

可以用作于不想让别人取地址,直接返回一个空。

总结:

本篇内容对六个默认成员函数进行了一个较为详细的分析,需要反复的复习并配合使用,其中构造,拷贝构造与运算符重载比较重要,在后面用的很多,后面还会有文章对这部分进行补充,例如友元函数和一些关键字。

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

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

相关文章

武汉星起航引领跨境电商新纪元,助力卖家扬帆远航全球市场

在全球化的商业浪潮中&#xff0c;跨境电商行业异军突起&#xff0c;成为连接全球市场的重要纽带。亚马逊&#xff0c;作为全球零售电商的巨擘&#xff0c;为无数卖家提供了走向国际市场的广阔舞台。在这片充满机遇与挑战的蓝海中&#xff0c;武汉星起航电子商务有限公司以其独…

R包安装失败怎么办?(一)msigdbr

R包安装失败 如果是网络原因&#xff08;error connection&#xff09;&#xff0c;就使用本地安装的方法。如果是网络原因&#xff0c;通常会出现安装超时&#xff0c;或者网络无法连接的提示 当你把timeout 设置到1000之后还会报错&#xff0c;怎么办&#xff1f; options…

在 Linux 中安装 Jenkins【图文详细教程】

安装 Jenkins 的系统要求&#xff1a; 最少 256MB 可用内存最少 1GB 可用磁盘空间JDK 8 / 11 /17&#xff08;Jenkins 是用 Java 写的&#xff0c;打包成 war 包&#xff09; 查看 JDK 的版本 Java JDK 在 Linux 中的安装可以参考&#xff1a;https://www.yuque.com/u27599042/…

实物档案管理系统是做什么的

实物档案管理系统是用于管理和组织实物档案的信息系统。它的主要功能包括记录、查找、归档实物档案&#xff0c;以及提供相关的管理功能。 具体来说&#xff0c;玖拓智能实物档案管理系统可以帮助单位完成以下任务&#xff1a; 1. 档案登记与归档&#xff1a;将新收到的实物档案…

斯坦福大学研究团队革新电机技术,助力机器人性能飞跃提升

文 | BFT机器人 在科技日新月异的今天&#xff0c;我们期望机器能够胜任的任务愈发复杂且多变。无论是为失去肢体的人提供动力的假肢&#xff0c;还是那些独立在外部世界自由穿梭的机器人&#xff0c;它们都需要在多种场景下展现出卓越的行动能力。 然而传统的标准电动机&…

mac电脑下安装和启动nginx

一,安装homebrew 必须安装了homebrew&#xff0c;可在终端输入命令brew -v查看是否已经安装,没安装的话安装一下: 如果未安装先安装&#xff08;网上很多文章&#xff09; 二,查看nginx是否存在 使用命令:brew search nginx查看nginx是否存在: 不存在的话,就使用brew inst…

服务消费微服务

文章目录 1.示意图2.环境搭建1.创建会员消费微服务模块2.删除不必要的两个文件3.检查父子模块的pom.xml文件1.子模块2.父模块 4.pom.xml 添加依赖&#xff08;刷新&#xff09;5.application.yml 配置监听端口和服务名6.com/sun/springcloud/MemberConsumerApplication.java 创…

社交革命:Facebook如何塑造数字社交的未来

引言 在当今数字化时代&#xff0c;社交媒体已成为人们生活的核心&#xff0c;而Facebook作为其中的领军者&#xff0c;一直在塑造着数字社交的未来。本文将深入探讨Facebook在数字社交领域的地位、影响力以及对未来社交的塑造作用&#xff0c;为读者揭示这场社交革命如何由Fa…

【MySQL】聊聊自增id用完怎么办?

在实际的开发中&#xff0c;一般都会将数据存储到数据库中&#xff0c;在设计表的时候&#xff0c;其实id如果达到最大值的话&#xff0c;会出现什么问题。其实主要分两种情况&#xff0c;一种是设置了主键id&#xff0c;另一种没有设置主键id。 表定义自增值id create table…

【Java程序设计】【C00389】基于(JavaWeb)Springboot的校园疫情防控系统(有论文)

基于&#xff08;JavaWeb&#xff09;Springboot的校园疫情防控系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过…

​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结

接上次博客&#xff1a;Redis&#xff08;四&#xff09;&#xff1a;持久化和事务&#xff1a;RDB&#xff08;定期备份&#xff09;【触发机制、流程说明、文件的处理、优缺点】、AOF&#xff08;实时备份&#xff09;【使用AOF、命令写入、文件同步、重写机制、启动时数据恢…

鸿蒙HarmonyOS应用开发之创建NDK工程

下面通过DevEco Studio的NDK工程模板&#xff0c;来演示如何创建一个NDK工程。 说明&#xff1a; 不同DevEco Studio版本的向导界面、模板默认参数等会有所不同&#xff0c;请根据实际工程需要&#xff0c;创建工程或修改工程参数。 通过如下两种方式&#xff0c;打开工程创建向…

贪心算法相关题目

文章目录 1. 什么是贪心&#xff1f;2. 分发饼干3. 摆动序列4. 最大子数组和5. 买卖股票的最佳时机 II6. 跳跃游戏7. 跳跃游戏 II8.K 次取反后最大化的数组和9.加油站10.分发糖果11.柠檬水找零12.根据身高重建队列13.用最少数量的箭引爆气球14. 无重叠区间15.划分字母区间16.合…

学习鸿蒙基础(8)

一、BuilderParam装饰器 当开发者创建了自定义组件&#xff0c;并想对该组件添加特定功能时&#xff0c;例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法&#xff0c;将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题&#xff0c;ArkUI引…

程序汪若依微服务华为云Linux部署保姆教程

若依官方有3个版本&#xff0c;程序汪以前已经出了对应的安装部署视频教程 单应用版本 前后分离版本 微服务版本 本视频是若依微服务版本&#xff0c;如果基础的环境软件都不会安装建议看下程序汪的单应用和前后端分离版本教程&#xff0c; 欢迎点击进入 &#xff08;单应…

开源流程图表库(01):Mermaid.js生成流程图、时序图、甘特图等

一、Mermaid.js的特点 Mermaid.js是一个用于生成流程图、时序图、甘特图等各种图表的开源库。它使用简洁的文本语法来描述图表结构&#xff0c;并将其转换为可视化的图形。 Mermaid.js的主要特点包括&#xff1a; 简洁易用&#xff1a;Mermaid.js使用简单的文本语法来描述图表…

嵌入式培训3-28

编写一条学生链表&#xff0c;写一些能够像链表里边添加数据的函数 实现&#xff1a;将链表中的所有内容保存到文件中去 以及 读取文件中的所有内容&#xff0c;加载到链表里面 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ma…

Python爬虫如何快速入门

写了几篇网络爬虫的博文后&#xff0c;有网友留言问Python爬虫如何入门&#xff1f;今天就来了解一下什么是爬虫&#xff0c;如何快速的上手Python爬虫。 一、什么是网络爬虫 网络爬虫&#xff0c;英文名称为Web Crawler或Spider&#xff0c;是一种通过程序在互联网上自动获取…

初识C++之命名空间(namespace)

初识C之入门 命名空间(namespace) 文章目录 初识C之入门 命名空间(namespace)1.为什么要有命名空间2. 命名空间 namespace使用方法3. 作用域限定符(::&#xff09;和 命名空间(namespace)4. 命名空间的定义5. 命名空间的嵌套6. 命名空间的使用7. 总结 1.为什么要有命名空间 在C…

部署elementPlus离线版本

最近项目需要离线开发&#xff0c;不能联网查一些组件的api&#xff0c;于是决定搞一个离线版的文档 一、下载官方文档 下载地址 github地址 gitee地址 选择版本 直接下载压缩包 二、下载live-server插件 全局下载live-server插件 npm i live-server -gvscode下载 三…