内存管理:使用新运算符进行数组和动态分配

时间:2013-04-23 04:30:52

标签: c++ memory-management memory-leaks assignment-operator

内存管理:使用新运算符进行数组和动态分配

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

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] != '\0')
   len++;
 buffer = new char[len+1];
 for (int i = 0; i < len; i++)
   buffer[i] = right[i];
 buffer[len] = '\0';
}

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] = '\0';
  }
  return *this;
}

答案。 我不知道......你能帮帮我吗? 这个似乎也好。 新的,它也被删除。 内存泄漏在哪里?

请告诉我。 谢谢,

4 个答案:

答案 0 :(得分:1)

您需要提供一个构造函数,该构造函数分配指针成员( inact所有类的构造函数应该执行)和析构函数释放它。

此外,您需要提供一个复制构造函数,它执行指针成员的深层复制。

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

好读:
What is The Rule of Three?

此外,String是一个糟糕的名字,特别是因为存在std::string

答案 1 :(得分:1)

Rule of three:如果一个类定义了一个析构函数或一个复制构造函数或一个复制赋值运算符,它可能必须定义所有三个。

您的代码违反了此规则,因为在提供复制赋值运算符时不提供析构函数和复制构造函数。

答案 2 :(得分:0)

当您的String对象被销毁时,默认构造函数被调用,因为您没有定义它。默认的析构函数不会为你删除[]你的char数组,你必须声明并定义一个析构函数来执行此操作。

此外,您会发现使用strcpy()/ strncpy()比复制每个char的简单循环要快得多。 (至少在与GCC编译时)。

答案 3 :(得分:0)

您的代码有4个问题。

  1. 您的赋值运算符具有以下行:char* buffer = new char[len + 1];这是声明一个新的指针变量而不是使用类成员。这会将内存分配给指针,然后该指针超出范围,永远不会被删除,并且会导致内存泄漏并使您的类无法正常运行。
  2. 缺少析构函数意味着你的类会泄漏内存。析构函数负责释放您使用new[]分配的内存。
  3. 缺少复制构造函数意味着您的String类不能在许多情况下使用,包括在STL容器中。 STL容器要求类型具有公共复制构造函数,赋值运算符和析构函数。
  4. 面对异常,您不会强制执行类不变量。目标是让你的班级exception safe。在我所做的更改中,我尝试实现强大的异常保证,并在异常情况下保留类状态。考虑异常安全性是创建自己的类的一个重要方面 - 尤其是库类,如String。
  5. 以下是尝试修复所有这些问题的代码。为了保持代码简短,我将实现放入类而不是分离它。当然,在实际代码中你应该使用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;
    };