🍅
目录
☃️1.拷贝构造
🐝1.1 浅拷贝
浅拷贝是编译器可以执行的一种傻瓜拷贝模式,按bit为单位一个一个拷贝,适用于内置类型
比如
int a=10;
int b=a;
但是
int * a=&p;
int * b=a;
这样指针的拷贝是非常危险的,因为指针指向空间,会出现a,b指针都指向一块空间的情况
一旦用指针a对空间释放,但是指针b完全不知道自己的空间没了
所以会出现野指针(b)
并且同一块空间插入删除数据会互相影响,析构两次程序会崩溃
🐝1.2 深拷贝
对于自定义类型,只能深拷贝,编译器不能完成的一种拷贝
之前的浅拷贝指针 问题就在于浅拷贝没有自己开空间的能力,深拷贝就是针对这一问题的解决方案
//深拷贝
inline
String::String(const String& str)
{
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
}
可能会重复调用,所以写成了内置类型
函数名和类名相同所以是一个构造函数,参数和类名相同,所以是拷贝构造,会开辟新空间,所以是深拷贝
🐝1.3拷贝构造
拷贝构造是构造函数的一个重载,使用同类对象初始化创建对象
什么情况下需要拷贝构造?
自己实现了析构函数释放空间
class Student
{
public:
Student()
{
age = 20;
}
Student(const Student& s)
{
age = s.age;
}
private:
int age;
char gender[5];
};
int main()
{
Student s1 ;
Student s2 = s1;
}
函数名和类名相同
const是最好加上,这样可以避免权限放大
用传引用,因为传值的方式会调用该函数类的拷贝构造函数,(因为自定义的类型要调用拷贝构造函数),从而无穷递归
☃️2.赋值重载
🐝2.1运算符重载
是一个有特殊函数名的函数,有返回类型,函数名字,以及参数列表
函数名:operator 需要重载的运算符号
函数原型:返回类型 operator 操作符(参数列表)
比如
注意:
不能通过连接其他符号来创造新的操作符 例如 operator@
重载操作符必须有一个类 类型的 参数
用于内置类型的运算符含义不能改变,比如operator+就应该实现两个类类型对象的 加 操作
为什么加const和为什么传引用和拷贝构造是一样的
.* :: sizeof 三目操作符 . 这五种运算符不能重载
支持复用!!!!!!!!比如
bool operator <=(const Date& d)
return (*this == d) || (*this < d);
🐝2.2赋值重载
把一个对象赋给另一个对象的函数,针对两个已经存在的对象
// d1 - 100
Date Date::operator-(int day)
{
_day -= day;
while (_day<1 )
{
_month--;
if (_month < 1)
{
_year--;
_month = 12;
}
_day += Getday(_year, _month);
}
//_day = Getday(_year, _month) - _day;
return *this;
}
这里无需传引用,因为传参的时候会调拷贝构造,前面已经写好拷贝构造函数即可,不会出现无穷递归
但是最好用传引用,因为用手能吃饭,但是用筷子最好
可以写不带返回值的,但返回值是为了支持连续赋值,保持运算符的特性
例如
int c=10,a,b;
a=b=c;
从右往左走,先看到把c给给b,这步运算是有返回值的(就是b),把返回值再给a
为了避免自己赋给自己的情况,可以加上一个判断
if(this != &d)
{
// 正常赋值
}
☃️3.默认生成的拷贝构造和赋值重载
自定义类型:调这个成员的拷贝构造/赋值重载
内置类型:浅拷贝