输出结果为:

首先结果并不符合预期,我们希望b对象中的字符串也是I love BIT但是输出为空,这是因为b->value和a->value指向了同一片内存区域,当delete a的时候,该内存区域已经被收回,所以再用b->value访问那块内存实际上是不合适的,而且,虽然我运行时程序没有崩溃,但是程序存在崩溃的风险呀,因为当delete b的时候,那块内存区域又被释放了一次,两次释放同一块内存,相当危险呀。
我们用valgrind检查一下,发现,相当多的内存错误呀!

其中就有一个Invalid free 也就是删除b的时候调用析构函数,对已经释放掉对空间又释放了一次。
那么深层复制应该怎样写呢?
代码如下:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
using namespace std;
class Str{
public:
char *value;
Str(char s[])
{
cout<<"调用构造函数..."<<endl;
int len = strlen(s);
value = new char[len + 1];
memset(value,0,len + 1);
strcpy(value,s);
}
Str(Str &v)
{
cout<<"调用拷贝构造函数..."<<endl;
int len = strlen(v.value);
value = new char[len + 1];
memset(value,0,len + 1);
strcpy(value,v.value);
}
~Str()
{
cout<<"调用析构函数..."<<endl;
if(value != NULL)
{
delete[] value;
value = NULL;
}
}
};
int main()
{
char s[] = "I love BIT";
Str *a = new Str(s);
Str *b = new Str(*a);
delete a;
cout<<"b对象中的字符串为:"<<b->value<<endl;
delete b;
return 0;
}
结果为:

这次达到了我们预想的效果,而且,用valgrind检测一下,发现,没有内存错误!

所以,写拷贝构造函数的时候,切记要注意指针的浅层复制问题呀!
好的,回顾了一下拷贝构造函数,下面回到移动构造函数上来。
有时候我们会遇到这样一种情况,我们用对象a初始化对象b,后对象a我们就不在使用了,但是对象a的空间还在呀(在析构之前),既然拷贝构造函数,实际上就是把a对象的内容复制一份到b中,那么为什么我们不能直接使用a的空间呢?这样就避免了新的空间的分配,大大降低了构造的成本。这就是移动构造函数设计的初衷。










