默认拷贝构造函数在大部分情况下,都可以正常运行。但是如果类里定义了堆内存的成员变量时,默认的拷贝构造函数不会给堆成员变量重新分配空间,造成两个对象的堆内存成员指向同一个内存块,如果其中一个对象释放了该内存块,另一个对象就会访问非法的内存。
class TestSimple
{
public:
TestSimple()
{
cout << "TestSimple Constructor...!" << endl;
pStr = new char[120];
char *tmp = "I'm a heap var!";
strncpy_s(pStr, 120, tmp, strlen(tmp));
};
/*TestSimple(TestSimple&){};*/
~TestSimple()
{
if (pStr)
{
cout << "TestSimple Destructor...!" << endl;
delete[] pStr;
pStr = nullptr;
}
};
void SetNum(int iNum)
{
num = iNum;
}
int GetNum() const
{
return num;
}
void PrintStr()
{
cout <<"pStr:"<< pStr << endl;
}
private:
int num = 5;
char *pStr;
};
TestSimple * TheFunc()
{
TestSimple *pTestSimple = new TestSimple();
pTestSimple->PrintStr();
cout << "pTestSimple address:" << pTestSimple << endl;
return pTestSimple;
}
char * GetStr()
{
char *pstr = "dfdfdd dsfd";
return pstr;
}
int _tmain(int argc, _TCHAR* argv[])
{
TestSimple *pTestSimple = new TestSimple();
pTestSimple->PrintStr();//打印成员变量:申请在堆内存的变量
TestSimple CopyTestSimple(*pTestSimple);//拷贝对象
if (pTestSimple)//释放申请在堆的对象
{
delete pTestSimple;
pTestSimple = nullptr;
}
return 0;
}
输出:
TestSimple Constructor...!
pStr:I'm a heap var!
TestSimple Destructor...! <span style="font-family: Arial, Helvetica, sans-serif;"> //</span><span style="font-family: Arial, Helvetica, sans-serif;">pTestSimple </span><span style="font-family: Arial, Helvetica, sans-serif;">对象释放,成功</span>
TestSimple Destructor...! //<span style="font-family: Arial, Helvetica, sans-serif;">CopyTestSimple 对象释放,失败</span>
此时运行时报错pHead->nBlockUse
分析:
两个对象指向同一个内存块,在pTestSimple被释放后,堆内存已释放,CopyTestSimple去释放堆内存已经非法了。
解决:
增加拷贝构造函数的定义,并且在拷贝构造函数中给堆成员变量重新分配内存,并将被拷贝对象的对应值赋给当前对象。
TestSimple(TestSimple& obj)
{
cout << "TestSimple Copy Constructor...!" << endl;
pStr = new char[120];
strncpy_s(pStr, 120, obj.pStr, strlen(obj.pStr));
};