文章目录
让程序在运行时决定内存分配,而不是在编译时决定
00.日志
2022/04/18 起笔
1 特殊成员函数
C++自动提供了以下成员函数
1.1 默认构造函数
如果没有提供任何构造参数,C++将创建默认构造函数
不接受任何参数,也不执行任何操作
自己定义默认构造函数两种方式(之前写过),二选一
1.1.1 编译器的构造函数如何初始化,全都为零么?
1.2 复制构造函数
用于将一个对象复制到新创建的对象中
用于初始化过程中(包括按值传递参数),而非常规的赋值过程中
函数原型
Class_name(const Class_name &)
1.2.1 调用时机
本质:每当程序生成了对象副本时
常见1: 新建一个对象并且将其初始化为同类现有对象时
举例
StringBad ditto(motto);
StringBad metoo = motto;
StringBad also = StringBad(motto);
StringBad * p = new StringBad(motto);
常见2:按值传递(初始化形参)、函数返回对象、编译器生成临时对象(三个vector相加,可能生成临时对象保存中间结果)
(故我们更应该使用按引用传递对象——节省调用构造函数的时间以及存储新对象的空间)
1.2.2 功能
默认的复制构造函数逐个复制非静态成员(成员复制也称为浅复制),复制的是成员的值
1)如果成员本身就是类对象,使用这个类的复制构造函数来复制成员对象
2)静态函数不受影响,其属于整个类不是各个对象
1.2.3 使用注意事项
1)如果类中包含这样的静态成员:其值在新对象被创建时发生变化
——解决:应该提供显式复制的构造函数来处理计数问题;
2)
-如果类中包含了使用new初始化的指针成员,隐式复制构造函数是按值赋值的,析构函数被调用会出现”释放已经释放的内存”的问题,其导致的后果可能有:程序终止/字符串乱码
——解决:应当定义一个复制构造函数,以复制指向的数据,而非指针,即进行深度赋值(deep copy)(会复制指针引用的结构,浅复制只是复制指针值)
1.2.4 类中的赋值运算符
我们知道C++允许类对象赋值——通过自动为类重载赋值运算符实现
并且其只能由类成员函数重载——会用到this指针实现自我以及连续赋值
原型
Class_name & Class_name::operator=(const Class_name &)
特点:如同隐式复制函数的实现一般进行浅复制
解决:与前面类似,但有些许不同
- 目标对象可能引用以前的数据,先使用delete[]来释放
- 函数应当避免赋值给自身,否者前一条可能删除对象的内容
- 函数返回一个指向调用对象的调用(连续赋值)
- 赋值操作不创建新对象,不必考虑调整计数类静态数据成员的值
StringBad & StingBad::operator=(const StringBad & st){
if(this == &st) return *this;
delete [] str;
...显式更新操作
return *this;
}