2013-04-24 75 views
0

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

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 
} 
+0

它应该在析构函数中释放,如果你已经正确实现它。 – juanchopanza 2013-04-24 22:12:29

+7

不完全是重复的,但你需要了解所有关于[Rule of Three](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-ree)如果你打算编写一个资源管理类。 – 2013-04-24 22:14:00

+0

是的,我知道,但是析构函数会释放赋值运算符中分配的内存吗?我认为它只会释放拷贝构造函数中分配的内存。 – vkaul11 2013-04-24 22:15:41

回答

3

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

{ 
    MyString s = "Something"; 
} 

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

比方说,你像这样使用,而不是:

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

现在MyString对象以相同的方式构建,为字符串数据分配内存。第二行然后将调用赋值操作符。如果按照您所描述的那样执行,则现有分配的char阵列将为deleted,并且将分配包含与some_other_string相同的字符串数据的新阵列。 这个新分配的数组将在s超出范围时被析构函数销毁。

破坏者只是delete[] s无论成员str指向。赋值运算符被调用后,它是新分配的数组。

+0

感谢您的回答。它说得很清楚。我在想如果析构函数只被调用由构造函数分配的内存而不是赋值操作符。 – vkaul11 2013-04-24 22:20:38

+0

尽管它的分解效果还不错,但它忽略了在释放旧分区之前必须分配新的内存块,或者至少必须确保当指针指向已删除的分块时你分配新的。 – 2013-04-24 23:04:32

0

当您分配字符串数组来保存rhs的内容副本时,您将覆盖值str。如果您在覆盖之前未删除str,则永远无法删除其用于指向堆的内容。它用来指向的内存块仍然保留在堆中,并且将不可用于重新使用。如果你的程序做了足够多的时间,你将会在堆中空间不足,你的程序将会死亡。这被称为内存泄漏。

0

首先,您不必删除赋值 运算符。如果您将指针 覆盖到先前动态分配的内存,则只需要删除。 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成员的长度,而 比混合strlen和长度成员。