C++赋值操作符中为什么需要删除已分配的内存?[副本]

d5vmydt9  于 2023-08-09  发布在  其他
关注(0)|答案(5)|浏览(97)

此问题在此处已有答案

Why delete is needed in the definition of the copy-assignment operator?(4个答案)
7年前就关门了。
为什么我们需要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
}

字符串

omqzjyyz

omqzjyyz1#

这不是一个复制构造函数,它是赋值运算符。您需要delete[],因为被赋值的对象已经保存了以前的值。
这段代码也不是很好,因为首先删除旧值,然后分配新值…但是分配可能抛出异常,并且在这种情况下,对象将保持指向解除分配的区域的指针。一个更好的方法是先分配然后删除旧值(异常永远不应该被允许从析构函数中逃逸...参见此链接以获得解释),因此分配成功或失败都不会损害任何东西。
一个常见的习惯用法是实现一个复制构造函数和一个交换操作(交换两个示例的内容,保证不会抛出异常)。然后你实现了assignment operator combining the two ...这需要较少的代码,并且从异常处理的观点来看是健壮的。

ryevplcw

ryevplcw2#

答案是,你必须释放内存,因为如果你不这样做,那么它就会丢失,因为你正在为新的分配重用指针。无论如何,如果你正在学习运算符,通常用复制构造+无抛出交换来编写operator=

class MyString {
   char* str;
   int len;
public:
   MyString( const MyString& rhs ) : str( new char[ rhs.len ] ), len( rhs.len ) {
      memcpy( str, rhs.str, len );
   }
   ~MyString() {
      delete str;
   }
   friend void swap( MyString & lhs, MyString & rhs ) throw() {
      using std::swap;
      swap( lhs.str, rhs.str );
      swap( lhs.len, rhs.len );
   }
   MyString& operator=( MyString rhs ) { //note: by value
      swap( *this, rhs );
      return *this;
   }
};

字符串
注意,执行的操作是类似的。现在的差异:

  • 整体代码较少。复制时需要执行的任何操作将仅在复制构造函数中实现,赋值运算符 * 借用 * 该代码。
  • 不需要检查自分配,因为复制是在释放旧内存之前执行的
  • 此实现是异常安全的:如果在分配内存(或复制构造函数中的任何其他操作)时出现问题,则该操作没有副作用
  • 自分配的性能较低,因为新的内存被分配,然后被复制和释放。但是从临时变量(右值表达式)赋值会更快,因为编译器可以省略副本。只有当度量值指向代码中的瓶颈时,才应该考虑性能。
jqjz2hbq

jqjz2hbq3#

这不是一个复制构造函数。只是个复印员。所以这个->str将指向先前分配的内存。如果在这个->str被赋予一个新值之前没有释放内存,那么它将永远不会被释放,因为它唯一的引用已经被覆盖了。因此,如果没有delete语句,该方法将泄漏内存。

kqqjbcuj

kqqjbcuj4#

如果没有delete[]语句,您将分配内存而不会再次释放它。如果你的程序运行的时间足够长,你最终会耗尽内存。
new char[]调用分配新的内存并产生一个指向已分配内存的指针。您将此内存存储在this->str中-覆盖存储在this->str中的前一个指针。

zaq34kh6

zaq34kh65#

请参阅Scott Meyers,Effective C++,第2版,第11至17项,以了解对该主题的全面处理。
另外:stackoverflow

相关问题