问题描述
- C++ 操作符重载的内存释放问题
-
=操作符重载,给复构造函数进行赋值时的代码如下:MyString & MyString::operator =(const MyString &str)
{
if(this == &str)
return *this;delete []m_pData; //**???????????????????????????? ** m_pData = NULL; m_pData = new char(strlen(str.m_pData) + 1); strcpy (m_pData, str.m_pData); return *this;
}
class MyString
{
public:
....
private:
char *m_pData;
}在函数中为什么还要是对原有的内存进行释放,即delete []m_pData,直接赋值 m_pData = str.m_pData, 这样不行吗?
请大神指点。
解决方案
有两个问题:
1. 如果不delete,那么m_pData
重新赋值后,原先指向的的内存不能被访问,也没有被回收给程序继续使用,相当于你的内存就减小了一块,也就是内存泄漏。
2. 不管是否delete,执行m_pData = str.m_pData
都是错误的。因为这样,两个指针指向的是同一片地址,例如你执行str1 = str2
,如果按你的方式来实现,那么以后修改str2中的字符串时,由于str1中的m_pData
也指向同一片区域,因此str1中的字符串也会被修改。一般来说,这不是我们希望看到的结果。
类似于这样:
int a = 1, b = 2;
a = b;
b = 3;
那么我们希望此时a的值等于2,而不是3。如果执行了b = 3之后,a的值也变成了3,那自然是不符合预期的。
解决方案二:
赋值后,就指向了新的对象,那原来的对象中分配的空间就造成了了内存泄露,所以先释放
解决方案三:
原有的内存空间与新赋值的内存空间长度有可能不一致。如果新赋值的内存空间长度大于原有的内存空间长度,需要重新开辟空间存储。所以需要现删除原有的内存空间,然后重新分配内存空间。否则有可能造成内存泄露。
解决方案四:
#if 1
class MyString
{
public:
MyString(){}
MyString(char str)
{
if (NULL == str)
{
m_pData = new char[1];
m_pData[0] = '';
}
else
{
m_pData = new char[strlen(str) + 1];
strcpy_s(m_pData, strlen(m_pData), str);
}
}
MyString & operator =(const MyString &str);
char Print()
{
return m_pData;
}
~MyString()
{
delete[]m_pData;
m_pData = NULL;
}
private:
char *m_pData;
};
MyString & MyString::operator =(const MyString &str)
{
if (this == &str)
return this;
//delete[]m_pData; //*???????????????????????????? **
//m_pData = NULL;
//m_pData = new char(strlen(str.m_pData) + 1);
//strcpy_s(m_pData, strlen(m_pData), str.m_pData);
m_pData = str.m_pData;
return *this;
}
int main()
{
MyString str1 = "asd";
MyString str2;
str2 = str1;
cout << str2.Print() << endl;
return 0;
}
#endif
其一,浅拷贝只是拷贝了指针,使得两个指针指向同一个地址,这样在对象块结束,调用函数析构的时,会造成同一份资源析构2次,即delete同一块内存2次,造成程序崩溃。
其二,浅拷贝使得obj.m_data和obj1.m_data指向同一块内存,任何一方的变动都会影响到另一方。
其三,在释放内存的时候,会造成obj1.m_data原有的内存没有被释放(这句话,刚开始我不太理解,如果没有走自定义的拷贝构造函数,申请内存空间,A obj1(obj);也不走默认构造函数,走的是默认的拷贝构造函数,何来分配空间直说,更不会造成obj1.m_data原有的内存没有被释放,这里刚开始我一直有疑问),造成内存泄露。
事实是这样的,当delete obj.m_data, obj.m_data内存被释放后,由于之前obj.m_data和obj1.m_data指向的是同一个内存空间,obj1.m_data所指的空间不能在被利用了,delete obj1.m_data也不会成功,一致已经无法操作该空间,所以导致内存泄露。