先来说结论:当类中有指针类型成员变量的时候,一定要自定义拷贝构造和赋值运算符
原因:当我们在有指针类成员变量的时候,还是用默认拷贝构造函数(拷贝构造函数执行的时候会调用赋值符),默认赋值为浅拷贝,会导致两个对象指向同一块堆区空间,在最后析构的时候导致内存二次析构而出错!
下面来看一下代码的示例:
#include<iostream>
using namespace std;
#include<string.h>#define SIZE 10class SeqList
{int *data;int maxsize;int cursize;public:SeqList() :data(NULL), maxsize(SIZE), cursize(0){data = (int*)malloc(sizeof(int) * maxsize);}~SeqList() {free(data);data = NULL;}
};int main()
{SeqList seqa;SeqList seqb(seqa);return 0;
}
大家来看一下上述代码的分析以及错误原因:
现在我们来自定义拷贝构造函数和赋值运算符:
拷贝构造函数:
SeqList(const SeqList& Seq)
{maxsize = Seq.maxsize;cursize = Seq.cursize;data = (int*)malloc(sizeof(int) * Seq.maxsize);//得在堆区重新申请一块空间来确保不会二次析构memcpy(data, Seq.data, sizeof(int)* Seq.cursize);//将seq堆区的东西拷贝
}
下面来看一下为什么还需要对赋值运算符进重写:
#include<iostream>
using namespace std;
#include<string.h>#define SIZE 10class SeqList
{int *data;int maxsize;int cursize;public:SeqList() :data(NULL), maxsize(SIZE), cursize(0){data = (int*)malloc(sizeof(int) * maxsize);}~SeqList() {free(data);data = NULL;}
};int main()
{SeqList seqa;SeqList seqb;seqa = seqb;return 0;
}
我们来分析一下这里错误的原因:
下面我们来自定义等号运算符:
SeqList& operator=(const SeqList& Seq){if (this != &Seq){free(data); //将内存泄漏那一块提前给释放了data = (int*)malloc(sizeof(int) * Seq.maxsize);memcpy(data, Seq.data, sizeof(int) * Seq.cursize);maxsize = Seq.maxsize;cursize = Seq.cursize;}return *this;}
下面将代码整合起来:
#include<iostream>
using namespace std;
#include<Cstring>#define SIZE 10class SeqList
{int *data;int maxsize;int cursize;
private:public:SeqList() :data(NULL), maxsize(SIZE), cursize(0){data = (int*)malloc(sizeof(int) * maxsize);}SeqList(const SeqList& Seq){maxsize = Seq.maxsize;cursize = Seq.cursize;data = (int*)malloc(sizeof(int) * Seq.maxsize);memcpy(data, Seq.data, sizeof(int)* Seq.cursize);}SeqList& operator=(const SeqList& Seq){if (this != &Seq){free(data);data = (int*)malloc(sizeof(int) * Seq.maxsize);memcpy(data, Seq.data, sizeof(int) * Seq.cursize);maxsize = Seq.maxsize;cursize = Seq.cursize;}return *this;}~SeqList() {free(data);data = NULL;}
};int main()
{/*SeqList seqa;SeqList seqb(sqea);*/SeqList seqa;SeqList seqb;seqa = seqb;return 0;
}