内存管理:使用new操作符进行数组和动态分配



内存管理:数组和动态分配的新操作符

。在内存管理方面,发生了什么错误?

class String
{
public:
 String(const char right[]);
 String& operator= (const String& right);
 int length() const;
private:
 char* buffer;
 int len;
}
int String::length() const {return len;}
String::String(const char right[])
{
 len = 0;
 while (right[len] != '')
   len++;
 buffer = new char[len+1];
 for (int i = 0; i < len; i++)
   buffer[i] = right[i];
 buffer[len] = '';
}
String& String::operator= (const String& right)
{
 if (this != &right)
  { 
    delete[] buffer;
    len = right.length();
    char* buffer = new char[len + 1];
    for (int i = 0; i < len; i++)
      buffer[i] = right[i];
    buffer[len] = '';
  }
  return *this;
}

回答。我不知道……你能帮我吗?这个看起来也不错。新增,也已删除。内存泄漏在哪里?

请告诉我。谢谢你,

您需要提供分配指针成员的构造函数(实际上您的类的所有构造函数都应该这样做)和释放它的析构函数。

还需要提供一个复制构造函数来执行指针成员的深度拷贝。

String::String(const String& obj)
{
   ....
}

好读:
什么是"三法则"?

而且,String对于一个类来说是一个糟糕的名字,特别是因为存在一个std::string

规则三:如果类定义了析构函数、复制构造函数或复制赋值操作符,则可能必须同时定义这三者。

你的代码违反了这条规则,没有提供析构函数和复制构造函数,而提供了复制赋值操作符。

你的代码有4个问题。

  1. 你的赋值操作符有以下一行:char* buffer = new char[len + 1];这是声明一个新的指针变量,不使用类成员。这将分配内存给指针,然后超出作用域,永远不能被删除,这将是一个内存泄漏,使你的类不能工作。
  2. 缺少析构函数意味着你的类会泄漏内存。析构函数负责释放用new[]分配的内存。缺少复制构造函数意味着String类不能在许多情况下使用,包括在STL容器中。STL容器要求类型具有公共复制构造函数、赋值操作符和析构函数。
  3. 你没有在面对异常时强制你的类不变量。目标是使类异常安全。在我所做的更改中,我试图实现强异常保证,并在面对异常时保持类状态。考虑异常安全是创建自己的类的一个重要方面——尤其是像String这样的库类。

下面是试图修复所有这些问题的代码。为了保持代码简短,我将实现放入类中,而不是将其分开。当然,在实际代码中应该使用std::string.

class String
{
public:
    String() : len(0), buffer(nullptr)
    {}
    String(const char right[]) : len(0), buffer(nullptr)
    {
        if(!right)
            return;
        int temp_len = strlen(right);
        buffer = new char[temp_len+1];
        len = temp_len; // only set the length after the allocation succeeds
        strcpy(buffer, right);
    }
    // a copy constructor is essential for this class
    String(const String& right) : len(0), buffer(nullptr)
    {
        String temp(right.buffer);
        swap(temp);
    }
    // must have a destructor to avoid leaks
    ~String()
    {
        if(buffer) // only delete if it has been allocated
            delete[] buffer;
    }
    String& operator= (const String& right)
    {
        String temp(right.buffer);
        swap(temp);
        return *this;
    }
    int length() const
    {
        return len;
    }
private:
    void swap(String& rhs)
    {
        std::swap(buffer, rhs.buffer);
        std::swap(len, rhs.len);
    }
    char* buffer;
    int len;
};

当String对象被销毁时,由于没有定义默认构造函数,因此将调用默认构造函数。默认析构函数不会为你删除[]字符数组,你必须声明并定义一个析构函数来做这件事。

另外,您会发现使用strcpy()/strncpy()比简单的循环复制每个字符要快得多。

最新更新