释放由赋值运算符C ++分配的内存

时间:2013-04-24 22:10:55

标签: c++

我正在阅读这篇文章Why do we need to delete allocated memory in C++ assignment operator?,我对在赋值运算符中新操作分配的内存有疑问。在我们分配给MyString对象testObject后它将如何被释放?是否会在超出范围时调用testObject的析构函数,或者我必须显式调用delete以释放该内存?

const MyString& operator=(const MyString& rhs)
{ 
    if (this != &rhs) {
        delete[] this->str; // Why is this required?
        this->str = new char[strlen(rhs.str) + 1]; // allocate new memory
        strcpy(this->str, rhs.str); // copy characters
        this->length = rhs.length; // copy length
    }
    return *this; // return self-reference so cascaded assignment works
}

3 个答案:

答案 0 :(得分:3)

当你有这个时会发生什么?

{
  MyString s = "Something";
}

这将首先构造一个MyString,它可能会动态分配一个char数组来存储字符串数据。然后s变量超出范围,MyString对象被销毁。它的析构函数应该通过执行delete[] str来清理任何动态分配的内存。

让我们说你这样使用它:

{
  MyString s = "Something";
  s = some_other_string;
}

现在MyString对象以相同的方式构造,为字符串数据分配内存。然后第二行将调用赋值运算符。如果按照您的描述实现,则现有的已分配char数组将为delete d,并且将分配包含与some_other_string相同的字符串数据的新数组。然后这个新分配的数组,当s超出范围时,它将被析构函数销毁。

析构函数只是delete[] s成员str指向的任何内容。调用赋值运算符后,delete[]新分配的数组。

答案 1 :(得分:0)

当您分配字符串数组以保存str内容的副本时,您将覆盖值rhs。如果在覆盖它之前没有删除str,则永远无法删除它从堆中指向的内容。它以前指向的内存块仍将保留在堆中,并且不可用于重用。如果你的程序执行了这么多次,那么堆中的空间就会用完,你的程序就会死掉。这称为内存泄漏。

答案 2 :(得分:0)

首先,您不一定要在作业中删除 运营商。如果覆盖指针,则只需删除 以前动态分配的内存。一个更好的 MyString的实施将是跟踪。{1}} capactity,如果需要,只重新分配(和删除) 更多的能力。

此外,在您的实施中,您在分配之前删除。 如果分配,这将导致未定义的行为 失败;你必须在之前完成所有可能失败的事情 删除。在这种情况下,您不需要自我测试 分配;自我分配测试的必要性是 通常是你的任务操作员被打破的信号。

将这两件事放在一起,我们得到类似的东西:

MyString const&
MyString::operator( MyString const& other )
{
    if ( capacity < other.length ) {
        char* tmp = new char[ other.length ];
        delete str;
        str = tmp;
        capacity = other.length;
    }
    memcpy( str, other.str, other.length );
    length = other.length;
    return *this;
}

删除是有条件的,分配后删除, 而且我们总是使用length成员 而不是混合strlen和长度成员。