2 gegege123gege gegege123gege 于 2016.03.10 09:13 提问

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, 这样不行吗?

请大神指点。

4个回答

cxsmarkchan
cxsmarkchan   2016.03.10 09:31
已采纳

有两个问题:
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,那自然是不符合预期的。

gegege123gege
gegege123gege 写的太好了,的确是这样。非常感谢。
接近 2 年之前 回复
bdmh
bdmh   Ds   Rxr 2016.03.10 09:24

赋值后,就指向了新的对象,那原来的对象中分配的空间就造成了了内存泄露,所以先释放

qq423399099
qq423399099   Ds   Rxr 2016.03.10 09:25

原有的内存空间与新赋值的内存空间长度有可能不一致。如果新赋值的内存空间长度大于原有的内存空间长度,需要重新开辟空间存储。所以需要现删除原有的内存空间,然后重新分配内存空间。否则有可能造成内存泄露。

John_ToStr
John_ToStr   Rxr 2016.03.10 12:34

#if 1
class MyString
{
public:
MyString(){}
MyString(char str)
{
if (NULL == str)
{
m_pData = new char[1];
m_pData[0] = '\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也不会成功,一致已经无法操作该空间,所以导致内存泄露。

John_ToStr
John_ToStr 回复gegege123gege: 嗯嗯
一年多之前 回复
gegege123gege
gegege123gege 恩,是的,如果不进行delete,原来的那块内存就没有指针能够指向它,所以无法释放,造成了内存泄露。
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!