文章目录
- 析构函数
- 1.析构函数的定义:
- 2.析构函数的语法:
- 3.析构函数的特性:
- 拷贝构造函数
- 1.拷贝构造函数的定义:
- 2.拷贝构造函数的语法
- 3.拷贝构造函数的特性
- (1)拷贝构造函数是构造函数的一个重载形式**(这个其实也很好理解,由于构造函数实现的是对对象的初始化,而拷贝构造也是对对象的初始化,只不过需要把值进行拷贝,然后实现初始化,所以它们的功能是相似的,但它们的参数不同,所以它们构成函数的重载)**
- (2)拷贝构造参数只能有一个,并且这个参数只能是类的类型对象的引用,用传值的方式,编译器会直接报错,因为传值调用会引发拷贝构造函数的无穷递归。
- (3)如果没有自定义一拷贝构造函数编译器会自动生成一个默认的拷贝构造函数
- (4)浅拷贝和深拷贝
- 总结:
析构函数
1.析构函数的定义:
析构函数是为了完成清理工作的,但不是对对象本身的清理,局部对象的清理是由编译器自动完成的,析构函数是对对象中的资源的清理。
2.析构函数的语法:
~+类名()
class Stack
{
public:
//析构函数不需要传参过来,因为会有this指针传过来
~Stack()//析构函数:~+类名()
{
free(_a);
_a = nullptr;
_size = _capacity = 0;
}
private:
int* _a;
size_t _size;
size_t _capacity;
};
3.析构函数的特性:
(1)析构函数无参数无返回值
(2)一个类只有一个析构函数,若没有自定义析构函数,那么编译器会自动生成析构函数,注意:析构函数是不能重载的。(这个为挺好理解的,如果你有多个函数都能实现清理的功能,由于析构函数是编译器自动调用的,那么编译器就不知道要调用那个函数来清理对象所占的资源了)
(3)对象的生命周期结束时,编译器自动调用析构函数。
(4)编译器自动生成的析构函数,对自定义成员变量会去调用它的析构函数, 但编译器自动生成的构造函数和析构函数不会去初始化和清理内置类型/基本类型(int/char)
下面的代码如果输出~Time()这个字符串,就表示编译器自动生成的析构函数会去调用自定义类型的析构函数
class Time
{
public:
~Time()
{
cout << "~Time()" << endl;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 基本类型(内置类型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型
Time _t;
};
int main()
{
Date d;
return 0;
}
拷贝构造函数
1.拷贝构造函数的定义:
拷贝构造,顾名思义就是对一个对象的拷贝呗。
2.拷贝构造函数的语法
类名+(参数)
Date(const Date& d)
{
//防止下面赋值操作写错,给d去掉可修改的权限
_year = d._year;
_month = d._month;
_day = d._day;
}
3.拷贝构造函数的特性
(1)拷贝构造函数是构造函数的一个重载形式**(这个其实也很好理解,由于构造函数实现的是对对象的初始化,而拷贝构造也是对对象的初始化,只不过需要把值进行拷贝,然后实现初始化,所以它们的功能是相似的,但它们的参数不同,所以它们构成函数的重载)**
(2)拷贝构造参数只能有一个,并且这个参数只能是类的类型对象的引用,用传值的方式,编译器会直接报错,因为传值调用会引发拷贝构造函数的无穷递归。
(3)如果没有自定义一拷贝构造函数编译器会自动生成一个默认的拷贝构造函数
(4)浅拷贝和深拷贝
下面来判断一段代码,看看这个代码能否正常运行
typedef int DataType;
class Stack
{
public:
Stack(size_t capacity = 10)
{
_array = (DataType*)malloc(capacity * sizeof(DataType));
if (nullptr == _array)
{
perror("malloc申请空间失败");
return;
}
_size = 0;
_capacity = capacity;
}
void Push(const DataType& data)
{
// CheckCapacity();
_array[_size] = data;
_size++;
}
~Stack()
{
if (_array)
{
free(_array);
_array = nullptr;
_capacity = 0;
_size = 0;
}
}
private:
DataType* _array;
size_t _size;
size_t _capacity;
};
int main()
{
Stack s1;
s1.Push(1);
s1.Push(2);
s1.Push(3);
s1.Push(4);
Stack s2(s1);
return 0;
}
代码直接崩了,这是因为什么呢?容我慢慢道来
注意:当类没有涉及空间资源的开辟时,构造函数可自己写也可不写,一旦涉及资源的开辟时,构造函数必须自己写,防止出现浅拷贝问题。
总结:
今天总结了析构函数和拷贝构造函数。