在测试我的代码时,我一直都会遇到有关使用delete的错误,因为我的类的测试表指出在使用new []分配的数组上调用了delete。我在~~ IntVector中删除了两个扩展函数,扩展函数扩展了容量,同时为动态分配的数组重新分配内存。
如何正确使用删除以防止内存泄漏并解决此错误?
主档
#include "IntVector.h"
#include <iostream>
#include <vector>
using namespace std;
IntVector::~IntVector(){
delete[] data;
}
void IntVector::expand(){
cap = cap * 2;
int *data2 = data;
data = new int[cap];
data = data2;
delete data2;
delete[] data2;
}
void IntVector::expand(unsigned amount){
cap = amount;
int *data2 = data;
data = new int[cap];
data = data2;
delete data2;
delete[] data2;
}
头
#ifndef INTVECTOR_H
#define INTVECTOR_H
using namespace std;
class IntVector{
private:
unsigned sz;
unsigned cap;
int *data;
private:
void expand();
void expand(unsigned amount);
};
#endif
答案 0 :(得分:3)
使用new[]
进行分配时,您必须使用delete[]
。您的expand
函数使用普通delete
。它还包含一些其他错误(重新分配指针,双重删除等)。
你的拷贝构造函数在哪里?复制赋值运算符?您可能想了解the rule of three。
答案 1 :(得分:2)
你可能遇到了这个问题,因为你不遵守三个规则 - 你需要一个复制构造函数和一个赋值操作符,在你的类中执行深层复制。
如果您执行类似
的操作IntVector x(IntVector(10));
您将在x
中留下悬空指针,因为当临时IntVector(10)
超出范围时,原始内容将被取消分配。
答案 2 :(得分:0)
除了违规规则外,您还试图在expand
函数中删除变量两次:
void IntVector::expand()
{
cap = cap * 2;
int *data2 = data;
data = new int[cap];
data = data2;
delete data2; // this should not be here!
delete[] data2; // this will be a problem now!
}
您只能删除一次数据,如果您使用new[]
创建了某些内容,则需要使用delete[]
删除该数据。
你的两个扩展函数看起来应该更像:
// copy-swap
void IntVector::expand()
{
IntVector tmp;
tmp.reserve(cap * 2);
tmp.resize(sz);
std::copy(data, data + sz, tmp.data);
std::swap(*this, tmp);
}
或
// raw implementation
void IntVector::expand()
{
unsigned int newCap = cap * 2;
int* newData = new int[newCap];
std::copy(data, data + sz, newData);
delete [] data;
data = newData;
cap = newCap;
}
复制交换版本可以让你重用其他函数(析构函数,复制赋值运算符),并且更加异常安全。原始实现不应修改内部数据元素,直到新的内部数据元素已正确创建。这可以防止new
中可能引发的异常使您的矢量处于不良状态(例如,当cap
实际上不是您的容量时)。