赋值构造函数的用法即指针悬挂问题的产生和解决(中)——解决之道
上篇文章末尾谈到了指针悬挂的问题,这主要是由于浅层复制构造函数的原因。为了解决这个指针悬挂的问题,这时候我们就需要引进一个新的概念:深层复制构造函数。
下面,我们来介绍一下浅层复制构造函数与深层复制构造函数之间的区别与联系......
- 浅层复制构造函数:浅层构造赋值函数主要是将传递进来的对象的成员变量的所有值赋值给新对象的成员变量。这主要是由于下面这个语句造成的(博文《复制构造函数的用法及指针悬挂问题的产生和解决(上)》中的程序的第13行):
x=a.x;//把对象a中的指针成员变量x的值复制给了对象b中的指针成员变量x
上面这个语句就会产生一个问题,即对象b的指针成员变量b.x和对象a的指针成员变量a.x所保存的值是同一块内存空间的地址。如果我们析构了对象a,那么编译器会自动释放该内存地址,而b并不知道,这样就产生了指针悬挂的问题。这就是由于浅层复制构造函数的运作机理产生的,它只是将旧对象的数据复制给新对象的数据,而如果是指针对象,它复制的就是指针所保存的地址。上面这句话是不是有点绕啊,我们用下图来解释一下:
从上面这个图就可以非常清楚地看到,当我 们析构掉对象a的时候,编译器会自动释放堆中所创建的内存空间。而对于对象b而言,它压根就不知道有编译器释放堆中内存这么一回事,所以自然b.x就变成迷途指针了。 - 深层复制构造函数:浅层构造赋值函数主要功能虽然也是是将传递进来的对象的成员变量的所有值赋值给新对象的成员变量,但是有一点不同之处在于,先看程序:
x=new int;//创建一块新空间 *x=*(a.x);//把对象a中指针成员x所指向的值赋值给了利用深层赋值构造函数所创建的对象b的指针成员x
由上面的程序可以看出,其实深层复制构造函数中我们只添加了为成员指针指向的数据成员分配内存,同时在赋值的时候,我们是把旧对象中指针成员所指向的值复制给了新对象的指针成员,而不是地址,这样就可以避免指针悬挂的问题了。你可能会问,上面这么长一串话是啥意思哦?不解释,我们直接上图!
从上面这个图,我们就显而易见地看出深层复制构造函数的好处了!注意看如果我们析构了对象a,那么编译器只是会回收内存地址为A处得内存,而不会管内存地址为D处的值。这样就避免了利用浅层复制函数所产生的对象b的指针悬挂问题了。