C++ 释放赋值运算符C+分配的内存+;
我正在浏览这篇文章,我有一个关于赋值操作符中new操作分配的内存的问题。在分配给MyString对象testObject之后,如何释放它?testObject的析构函数是否会在超出范围时调用,或者我必须显式调用delete来释放内存C++ 释放赋值运算符C+分配的内存+;,c++,C++,我正在浏览这篇文章,我有一个关于赋值操作符中new操作分配的内存的问题。在分配给MyString对象testObject之后,如何释放它?testObject的析构函数是否会在超出范围时调用,或者我必须显式调用delete来释放内存 const MyString& operator=(const MyString& rhs) { if (this != &rhs) { delete[] this->str; // Why is this r
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
,它可能会动态分配一个char
s数组来存储字符串数据。然后s
变量超出范围,MyString
对象被销毁。它的析构函数应该通过执行delete[]str
清理任何动态分配的内存
比如说,您可以这样使用它:
{
MyString s = "Something";
s = some_other_string;
}
现在,MyString
对象以相同的方式构造,为字符串数据分配内存。然后,第二行将调用赋值运算符。如果按照您描述的方式实现,则现有分配的char
数组将是delete
d,并且将分配一个新数组,其中包含与some\u other\u string
相同的字符串数据。当s
超出范围时,析构函数将销毁这个新分配的数组
析构函数只是
delete[]
s成员str
指向的任何对象。调用赋值运算符后,它将delete[]
ing新分配的数组。当您使用此运算符时会发生什么
{
MyString s = "Something";
}
这将首先构造一个MyString
,它可能会动态分配一个char
s数组来存储字符串数据。然后s
变量超出范围,MyString
对象被销毁。它的析构函数应该通过执行delete[]str
清理任何动态分配的内存
比如说,您可以这样使用它:
{
MyString s = "Something";
s = some_other_string;
}
现在,MyString
对象以相同的方式构造,为字符串数据分配内存。然后,第二行将调用赋值运算符。如果按照您描述的方式实现,则现有分配的char
数组将是delete
d,并且将分配一个新数组,其中包含与some\u other\u string
相同的字符串数据。当s
超出范围时,析构函数将销毁这个新分配的数组
析构函数只是
delete[]
s成员str
指向的任何对象。调用赋值运算符后,它将delete[]
覆盖新分配的数组。分配字符串数组以保存rhs
内容副本时,您将覆盖值str
。如果您在覆盖它之前没有删除'dstr
,您将永远无法从堆中删除它用来指向的内容。它用来指向的内存块仍将保留在堆中,并且不可重复使用。如果您的程序执行此操作的次数足够多,则堆中的空间将耗尽,并且您的程序将死亡。这称为内存泄漏。当您分配字符串数组以保存rhs
内容的副本时,您正在覆盖值str
。如果您在覆盖它之前没有删除'dstr
,您将永远无法从堆中删除它用来指向的内容。它用来指向的内存块仍将保留在堆中,并且不可重复使用。如果您的程序执行此操作的次数足够多,则堆中的空间将耗尽,并且您的程序将死亡。这称为内存泄漏。首先,您不必在分配中删除
操作人员只有覆盖指针时才需要删除
以前动态分配的内存。更好的
MyString
的实现将是跟踪
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;
}
MyString常量&
MyString::运算符(MyString常量和其他)
{
if(容量<其他长度){
char*tmp=新字符[other.length];
删除str;
str=tmp;
容量=其他长度;
}
memcpy(str,other.str,other.length);
长度=其他长度;
归还*这个;
}
删除是有条件的,删除在分配之后,
我们总是使用length
成员表示长度,而不是
而不是混合strlen和length成员。首先,您不必在赋值中删除 操作人员只有覆盖指针时才需要删除 以前动态分配的内存。更好的
MyString
的实现将是跟踪
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;
}
MyString常量&
MyString::运算符(MyString常量和其他)
{
if(容量<其他长度){
char*tmp=新字符[other.length];
德勒