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

freeing memory allocated by assignment operator C++

本文关键字:内存 分配 C++ 赋值运算符 释放      更新时间:2023-10-16

我正在读这篇文章为什么我们需要删除C++赋值运算符中分配的内存?我有一个关于赋值运算符中新操作分配的内存的问题。在我们分配给一个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
}

出现这种情况时会发生什么?

{
  MyString s = "Something";
}

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

假设你这样使用它:

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

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

析构函数delete[]就是成员str指向的任何对象。在调用赋值运算符后,它就是新分配数组的delete[]

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

首先,您不必在赋值中删除操作人员只有覆盖指针时才需要删除到先前动态分配的存储器。一个更好的MyString的实施将跟踪容量,并且仅在需要时重新分配(和删除(更大的容量。

此外,在您的实现中,您可以在分配之前删除。如果分配失败;在删去在这种情况下,你不需要自我测试分配自我分配测试的必要性是通常是一个信号,表明你的作业操作员坏了。

把这两件事放在一起,我们得到了这样的东西:

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成员作为长度而不是混合CCD_ 19和长度构件。