C++结构函数和析构函数
结构函数和析构函数就是分别用于对象的初始化和清理,在我们不提供结构函数和析构函数时,编译器会提供结构函数和析构函数,但是是空实现。
结构函数
主要用于在创建对象时,为对象的成员属性赋值,结构函数由编译器自动调用,无需手动调用
结构函数又分为:无参结构函数、有参结构函数和拷贝结构函数
无参结构函数:即结构函数无参数 类名(){ };
有参结构函数:即结构函数有参数 类名(类型 变量,类型 变量 …){ };
拷贝结构函数:即将这份对象属性,拷贝到另一个对象一份 类名(const 类名 & 变量){ };
拷贝结构函数:
拷贝结构函数调用时的三种情况:(已创建好一个peoper类)
1.使用一个已经创建完毕的对象来初始化一个新对象
//1.用一个创建好的对象来初始化一个新对象
peoper p1(18);
peoper p2(p1);
2.值传递的方式给函数参数传值
//2.值传递的方式给函数参数传值
void fun2( peoper p)
{
}
3.以值方式返回局部对象
//3.以值方式返回局部对象
peoper fun3()
{
peoper p1;
return p1;
}
注意:此时return的值已经不是peoper p1的p1了,而是p1拷贝一份后的p1’了,二者的地址不一样了
拷贝结构函数分为浅拷贝结构函数和深拷贝结构函数;
浅拷贝结构函数:就是将对象的属性简单的拷贝给另一份;
深拷贝结构函数:在堆区重新申请空间,进行拷贝操作;
在堆区申请空间需要用new关键字,并且要拷贝的对象属性需要是指针形式,因为是在堆区申请的空间所以需要手动用关键字delete释放。
class peoper
{
public:
peoper(int age,int height)
{
p_age = age;
cout << "有参结构函数" << endl;
p_height = new int(height);//在堆区申请空间
}
peoper(const peoper & p)
{
p_age = p.p_age;
cout << "拷贝结构函数" << endl;
p_height = new int(*p.p_height);
}
~peoper()//析构结构函数,释放内存
{
if (p_height != NULL)//释放空间
{
delete p_height;
p_height = NULL;
}
cout << "析构函数" << endl;
}
int p_age;
int *p_height;
};
注意:如果属性是在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题。
解释:因为属性是在堆区开辟的,简单的浅拷贝只是对栈区的数据进行了完全拷贝,就会出现两个对象的属性指向同一块堆区内存,这样在进行析构函数时,与一个地址会被释放两次,编译器会报错。这时可以通过自己提供拷贝构造函数,将对象的属性和堆区的内存都进行了一次拷贝,这时两个对象属性是两个不同地址但是指向是同样数据。
C++编译器至少给一个类添加三个函数
- 默认构造函数(无参,函数体为空)
- 默认析构函数(无参,函数体为空)
- 默认拷贝构造函数 对属性进行值拷贝
结构函数调用规则:
1.如果用户定义了有参构造函数,C++不在提供无参构造函数,但是会提供 默认拷贝构造函数
2.如果用户定义了拷贝构造函数,C++不在提供其他构造函数
析构函数
主要用于对象销毁前系统自动调用,执行一些清理工作
结构形式:~ 类名() { }