C++类四个默认函数&深复制&浅复制

时间:2022-08-23 12:33:03

学习C++语言的同学都知道,C++中类是有默认的几个函数的,主要是有四个函数:

四个函数

  1. 默认构造函数:A(void),无参构造函数
  2. 拷贝(复制)构造函数:A(const A&a)。用一个对象A去为另一个对象赋值。
  3. 析构函数:~A(void)。释放掉A所占用的空间。
  4. 赋值函数:A &original = const A&a。使用一个对象a直接为另一个对象赋值。

默认的无参构造函数和析构函数不多讲,大家都很明白,析构函数不用手动调用,是在类生命期结束的时候系统自动调用的,析构函数主要是释放分配的空间的(delete和delete[]有类似之处)。

每个类只有一个赋值函数和一个析构函数,但是构造函数却可以有多个。对于任意的一个类,如果不编写上述四个函数,C++编译器会自动生成上述四个函数。那不仅要问了,既然C++编译器这么智能,为什么我们还要编写这四个函数呢?

因为这些缺省的拷贝构造函数和赋值函数都是采用“值”操作的方式,而不是“位”操作。这会导致什么问题呢?我们可以想一些,如果类中的成员变量使用了堆空间的时候,就会出现操作的是同一个地址的问题,也就是我们所说的深复制和浅复制的问题。

 

深复制和浅复制

所谓浅复制,就不是对整个对象的按照位的拷贝,而是仅仅拷贝了数值,就像上面所说的,如果这个类对象中有指针类型(堆空间),那么经过拷贝构造后得到的对象和原来的对象所指向的就是同一块内存空间,那这算是拷贝么??

深复制就不一样了,是对整个对象的按照位拷贝,当遇到指针(对空间)类型变量时候,会对整个指针空间拷贝。这样可以得到两个完全不同的对象。

 

拷贝构造函数和赋值函数

那么还有一个问题就是拷贝构造函数和赋值函数到底有什么区别呢?都是值拷贝,那他俩貌似也就一样吧。拷贝构造函数是在对象被创建时调用的,而赋值函数只能被已经存在了的对象调用。如下式子所示:

String a(“hello”);
String b(“world”);
String c
= a; // 调用了拷贝构造函数,最好写成c(a);
c = b; // 调用了赋值函数

 

总结

当类含有动态生成的数据成员,必须自定义析构函数以释放动态分配的内存,自定义复制构造函数(Copy Structor)和复制赋值操作符(Copy Assignment Operator)实现深复制。