对于类的构造函数我们已经有了初步的了解,这里我们对其拷贝构造函数进行讲解:
目录
拷贝构造函数:
1.拷贝构造函数的作用:
2.系统生成拷贝构造函数的缺陷
3.深拷贝的实现
侧面体现
拷贝构造函数:
这里我们将拷贝构造函数进行单独来讲,其原因是因为存在深拷贝和浅拷贝问题。这个问题在我初学时也特别困扰我,所以读者开始不会也不要对此想要放弃。接下来我们开始讲解:
1.拷贝构造函数的作用:
用类的对象初始话对象时就要调用拷贝构造函数进行构造
class Date
{public:Date(int year=2024,int month=7,int day=10){_year=year;_month=month;_day=day;}~Date(){}private:int _year,_month,_day;} ;int main()
{Date wang(2024,7,10);Date xiao(wang);//这里系统调用默认生成的拷贝构造函数return 0;
}
2.系统生成拷贝构造函数的缺陷
但是,系统默认生成的拷贝构造函数只是对数据的简单复制,这也就造成了浅拷贝问题:
这里我们可以看到在xiao和wang中指针p指向的空间位置相同,而我们希望的拷贝结果是两者的指针指向不同的空间位置,但是两个空间位置的数据是相同的。同时,在这里当程序运行结束时,析构函数会对该区域进行两次空间释放,从而导致程序运行报错。
这里我们可以将浅拷贝理解为简单的数据复制:
Date(Date&a){p=a.p;_year=a._year;_month=a._month;_day=a._day;}
3.深拷贝的实现
那么我们如何来解决这一问题来真正意义上实现类的拷贝呢,为此,我们需要自己定义拷贝构造函数,来完成对具有堆区内存开辟的类的拷贝:
class Date {public:Date(int year=2024,int month=7,int day=10) {_year=year;_month=month;_day=day;p=new int[10];}void Print() {cout<<p<<endl;}void setnumber(){for(int i=0;i<10;++i){*(p+i)=i;}}Date(Date&a){p=new int[10];//重新申请内存空间//数据拷贝for(int i=0;i<10;++i){*(p+i)=*((a.p)+i);} _year=a._year;_month=a._month;_day=a._day;}~Date() {delete []p;}private:int _year,_month,_day;int*p;} ;int main() {Date wang(2024,7,10);wang.setnumber();Date xiao(wang);//类拷贝构造初始化wang.Print();//打印地址xiao.Print();return 0;
}
将两个指针指向的空间位置进行打印:
这样两者指针的指向空间就会不一样,从而避免内存空间的重复释放。
侧面体现
这里也就体现出了一个析构函数的功能,其对于浅拷贝的检查功能。当出现浅拷贝时,由于析构函数会对申请空间进行多次释放,从而导致编译器报错