关于拷贝构造函数
1.参数应该为引用,并加上const
如果不是引用,是传值,那么就会有一次形参和实参的拷贝,这本身又是一次拷贝构造,因此会无限循环。
为啥加const 1.让const类型对象可以用来拷贝构造2.防止修改原对象。
2.默认拷贝构造函数
简单的赋值,浅拷贝,如果有手动开辟的堆空间,只是改变的指针指向并没有真正的复制。
什么时候回调用拷贝构造函数?
首先明白初始化和复制的区别
int a = 100; //以赋值的方式初始化 初始化
a = 200; //赋值
int b; //默认初始化
b = 29; //赋值
//stu1、stu2、stu3都会调用普通构造函数Student(string name, int age, float score)
Student stu1("小明", 16, 90.5);
Student stu2("王城", 17, 89.0);
Student stu3("陈晗", 18, 98.0);
Student stu4 = stu1; //调用拷贝构造函数Student(const Student &stu)
stu4 = stu2; //调用operator=()
stu4 = stu3; //调用operator=()
Student stu5; //调用普通构造函数Student()
stu5 = stu1; //调用operator=()
stu5 = stu2; //调用operator=()
四种情况会出现拷贝构造
1.将其他对象作为参数
Student stu1("小明", 16, 90.5); //普通初始化
Student stu2(stu1); //以拷贝的方式初始化
2.在创建对象的同时赋值
Student stu1("小明", 16, 90.5); //普通初始化
Student stu2 = stu1; //以拷贝的方式初始化
3. 函数的形参为类类型
4. 函数返回值为类类型
注意:函数的返回值为引用和值的区别。如果是在函数内部创建的变量,不能返回其引用
重载=
编译器默认会重载,简单的赋值拷贝。
Array &Array::operator=(const Array &arr){ //重载赋值运算符
if( this != &arr){ //判断是否是给自己赋值
this->m_len = arr.m_len;
free(this->m_p); //释放原来的内存
this->m_p = (int*)calloc( this->m_len, sizeof(int) );
memcpy( this->m_p, arr.m_p, m_len * sizeof(int) );
}
return *this;
}
1.返回值为引用:满足连续赋值的要求
2.判断是否是自己给自己赋值,如果不加判断,free(this->m_p); 会释放自己内存
3.const 两个目的同上
4.返回*this
这里没有考虑申请内存失败的问题。
更标准的写法如下
Array &Array::operator=(const Array &arr){
if (this != &arr){
Array temp(arr);
this->m_len = arr.m_len;
int*help = this->m_p;
this->m_p = temp.m_p;
temp.m_p = help;
}
return *this;
}
用拷贝构造的方式创建一个arr的副本,让this中的m_p和副本中的m_p交换,副本会在函数调用完毕后析构。
转换构造函数
当编译器知道转换规则的时候,可以自动进行类型转换
例如:
int a = 6;
a = 7.5 + a;
先将 a 转换为 double 类型,然后与 7.5 相加,得到和为 13.5。在向整型变量 a 赋值时,将 13.5 转换为整数 13,然后赋给 a。
同理,这种转换可以用于类,前提是要让编译器知道转换规则。
例如:cmplex是复数类
Complex c1(15.6, 89.9);
Complex c2;
c2 = c1 + 29.6;
声明了转换构造函数后,c2 = c1 + 29.6;就等价于
c2 = c1 + complex(29.6);
类型转换函数
将当前类类型转换为其他类型
operator type(){
//TODO:
return data;
}
例如:operator double() const { return m_real; } //转换为double类型
如果同时定义了类型转换函数和转换构造函数就会导致二义性,转换构造函数常用
Complex c1(24.6, 100);
float f = 12.5 + c1;
既可以complex(12.5)又可以将c1类型转换为double 二义性
类型转换
本质:对数据所占用的二进制位做出重新的解释,必要的时候还会修改数据,改变其二进制位,当知道转换规则的时候。
强制转换,无法对二进制位修改。(注意:这种修改是有利的,修改的不是原始数据,只是副本)
四种类型转换运算符