Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 释放赋值运算符C+分配的内存+;_C++ - Fatal编程技术网

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

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

我正在浏览这篇文章,我有一个关于赋值操作符中new操作分配的内存的问题。在分配给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
,它可能会动态分配一个
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
。如果您在覆盖它之前没有删除'd
str
,您将永远无法从堆中删除它用来指向的内容。它用来指向的内存块仍将保留在堆中,并且不可重复使用。如果您的程序执行此操作的次数足够多,则堆中的空间将耗尽,并且您的程序将死亡。这称为内存泄漏。

当您分配字符串数组以保存
rhs
内容的副本时,您正在覆盖值
str
。如果您在覆盖它之前没有删除'd
str
,您将永远无法从堆中删除它用来指向的内容。它用来指向的内存块仍将保留在堆中,并且不可重复使用。如果您的程序执行此操作的次数足够多,则堆中的空间将耗尽,并且您的程序将死亡。这称为内存泄漏。

首先,您不必在分配中删除 操作人员只有覆盖指针时才需要删除 以前动态分配的内存。更好的
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];
德勒