简单认知
构造函数:初始化对象成员属性,编译器自动调用
析构函数:对象销毁前自动调用,用于释放内存等一些清理工作
例
#include <iostream>
using namespace std;
class Dog{
public:
Dog()
{
cout<<"构造函数调用"<<endl;
}
~Dog()
{
cout<<"析构函数调用"<<endl;
}
};
void example()
{
Dog dog;
}
int main()
{
example();
return 0;
}
输出结果
分类
可分为有参构造和无参构造
或可分为普通构造和拷贝构造
一般情况下,系统会默认给类添加一个空实现的构造函数,空实现的析构函数和对属性进行拷贝的拷贝构造函数
有参构造和拷贝构造简单用法例:
#include <iostream>
using namespace std;
class Dog{
public:
Dog()
{
cout<<"构造函数调用"<<endl;
}
Dog(int a)
{
cout<<"有参构造的调用"<<endl;
}
~Dog()
{
cout<<"析构函数调用"<<endl;
}
Dog(const Dog &d)
{
cout<<"拷贝构造函数调用"<<endl;
}
};
void example()
{
Dog dog(1);//有参构造定义时传入参数
Dog dog1(dog);//拷贝构造定义时传入对象
}
int main()
{
example();
return 0;
}
结果
在用户定义了有参构造并且在创建对象的时候传入参数之后,无参构造不再调用
深拷贝与浅拷贝
浅拷贝
#include <iostream>
#include <string>
using namespace std;
class Dog{
public:
Dog()
{
cout<<"构造函数调用"<<endl;
}
Dog(string color)
{
my_color = color;
// cout<<"有参构造的调用"<<endl;
}
~Dog()
{
// cout<<"析构函数调用"<<endl;
}
string my_color;
};
void example()
{
Dog dog("white");//有参构造定义时传入参数
cout<<"dog的颜色为:"<<dog.my_color<<endl;
Dog dog1(dog);//拷贝构造定义时传入对象
cout<<"dog1的颜色为:"<<dog1.my_color<<endl;
}
int main()
{
example();
return 0;
}
结果
我们并没有定义拷贝构造函数,但是当我们定义dog1对象并把dog作为参数传进去的时候,就相当于调用自带默认的拷贝构造函数,依照传进去的dog简单拷贝了一个新的对象dog1,所以dog1的颜色也是白色,这就是浅拷贝。
此时我们新增一个属性年龄
#include <iostream>
#include <string>
using namespace std;
class Dog{
public:
Dog()
{
cout<<"构造函数调用"<<endl;
}
Dog(string color,int age)
{
my_color = color;
my_age = new int(age);//指针接收创建在堆区的数据
// cout<<"有参构造的调用"<<endl;
}
~Dog()
{
// cout<<"析构函数调用"<<endl;
}
string my_color;
int * my_age;
};
void example()
{
Dog dog("white",2);//有参构造定义时传入参数
cout<<"dog的颜色为:"<<dog.my_color<<'\t'<<"dog的年龄为:"<<*dog.my_age<<endl;
Dog dog1(dog);//拷贝构造定义时传入对象
cout<<"dog1的颜色为:"<<dog1.my_color<<'\t'<<"dog1的年龄为:"<<*dog1.my_age<<endl;
}
int main()
{
example();
return 0;
}
输出结果
没有问题
这里面我们在堆区申请了一块内存没有释放,如果我们在析构函数函数去释放my_age的时候,会发现程序会崩溃。
原因:
当我们在定义dog的时候,一共有两个属性,一个是颜色,一个是年龄,其中年龄是在堆区创建的指针类型,当我们利用浅拷贝定义了dog1对象的时候,dog1年龄指针也指向了与dog年龄指针一样的地址,所以如果在析构函数函数中去释放这一块内存,相当于释放两次一样的内存,程序出错。
这是浅拷贝带来的问题,堆区内存重复释放
利用深拷贝来解决,自定义拷贝构造函数,重新申请内存接收my_age
#include <iostream>
#include <string>
using namespace std;
class Dog{
public:
Dog()
{
cout<<"构造函数调用"<<endl;
}
Dog(string color,int age)
{
my_color = color;
my_age = new int(age);//指针接收创建在堆区的数据
// cout<<"有参构造的调用"<<endl;
}
~Dog()
{
if(my_age != NULL)
{
delete my_age;
my_age = NULL;
}
// cout<<"析构函数调用"<<endl;
}
Dog(const Dog &d)
{
my_color = d.my_color;
my_age = new int(*d.my_age);//重新申请内存接收拷贝的指针
}
string my_color;
int * my_age;
};
void example()
{
Dog dog("white",2);//有参构造定义时传入参数
cout<<"dog的颜色为:"<<dog.my_color<<'\t'<<"dog的年龄为:"<<*dog.my_age<<endl;
Dog dog1(dog);//拷贝构造定义时传入对象
cout<<"dog1的颜色为:"<<dog1.my_color<<'\t'<<"dog1的年龄为:"<<*dog1.my_age<<endl;
}
int main()
{
example();
return 0;
}