内存管理:数组和动态分配的新操作符
。在内存管理方面,发生了什么错误?
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个问题。
- 你的赋值操作符有以下一行:
char* buffer = new char[len + 1];
这是声明一个新的指针变量,不使用类成员。这将分配内存给指针,然后超出作用域,永远不能被删除,这将是一个内存泄漏,使你的类不能工作。 缺少析构函数意味着你的类会泄漏内存。析构函数负责释放用 - 你没有在面对异常时强制你的类不变量。目标是使类异常安全。在我所做的更改中,我试图实现强异常保证,并在面对异常时保持类状态。考虑异常安全是创建自己的类的一个重要方面——尤其是像String这样的库类。
new[]
分配的内存。缺少复制构造函数意味着String类不能在许多情况下使用,包括在STL容器中。STL容器要求类型具有公共复制构造函数、赋值操作符和析构函数。下面是试图修复所有这些问题的代码。为了保持代码简短,我将实现放入类中,而不是将其分开。当然,在实际代码中应该使用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()比简单的循环复制每个字符要快得多。