导致堆缓冲区错误的动态分配数组的析构函数



所以我有一个分配来编写一个版本的向量库而不使用它。我需要使用动态分配的数组,但是它们的析构函数会导致错误。这是我的代码:

class orderedVector {
friend ostream& operator<<(ostream&, const orderedVector&);
friend istream& operator>>(istream&, orderedVector&);
public:
orderedVector(int = 9);
~orderedVector();
int getSize() const;
int getCapacity() const;
void doubleCapacity();
bool find(int) const;
void insert(int);
void remove(int);
void findSum(int);
private:
int size;
int capacity;
int* ptr;
};
orderedVector::orderedVector(int c) {
capacity = c;
size = 0;
ptr = new int[c];
}
orderedVector::~orderedVector() {
delete[] ptr;
}
int orderedVector::getSize() const {
return size;
}
int orderedVector::getCapacity() const {
return capacity;
}
void orderedVector::doubleCapacity() {
int newCapacity = capacity * 2;
orderedVector temp(capacity);
for (int i = 0; i < size; i++) {
temp.ptr[i] = ptr[i];
}
ptr = new int[newCapacity];
for (int i = 0; i < size; i++) {
ptr[i] = temp.ptr[i];
}
capacity = newCapacity;
}
bool orderedVector::find(int number) const {
for (int i = 0; i <= size; i++)
if (number == ptr[i])
return true;
return false;
}
void orderedVector::insert(int number){
if (find(number)) {
return;
}
if (size == capacity)
doubleCapacity();
if (size == 0)
ptr[0] = number;
else {
int checkpoint = size;
for (int i = 0; i < size; i++) {
if (number < ptr[i]) {
checkpoint = i;
break;
}
}
for (int i = size-1; i >= checkpoint; i--) {
ptr[i + 1] = ptr[i];
}
ptr[checkpoint] = number;
}
size++;
}           
void orderedVector::remove(int number) {
if (find(number) == false)
cout << "Number does not exist in the vector.n";
else {
int checkpoint = 0;
for (int i = 0; i <= size; i++)
if (ptr[i] == number)
checkpoint = i;
for (int i = checkpoint; i < size; i++)
ptr[i] = ptr[i + 1];
}
ptr[size] = 0;
size--;
}
void orderedVector::findSum(int number) {
for (int i = 0; i <= size; i++) {
for (int j = i+1; j <= size; j++) {
if (ptr[i] + ptr[j] == number) {
cout << "The two numbers that have a sum of " << number
<< " are " << ptr[i] << " and " << ptr[j] << endl;
return;
}
}
}
cout << "No two numbers found that give a sum of " << number << endl;
}
ostream& operator<<(ostream& output, const orderedVector& vector) {
for (int i = 0; i < vector.size; i++)
output << vector.ptr[i] << "    ";
output << endl;
return output;
}
istream& operator>>(istream& input, orderedVector& vector) {
int x = 0;
for (int i = 0; i < vector.capacity; i++) {
input >> x;
vector.insert(x);
}
return input;
}

似乎当我初始化一个元素并且数组完全填充时,我收到此错误: 检测到堆损坏,CRT 检测到应用程序在堆缓冲区结束后写入内存。

我知道它是析构函数,因为当我删除它时,不会发生任何错误。 此外,当我的矢量元素没有完全填充(容量大于大小(时,不会发生错误。 我想知道如何解决这个问题,或者删除运算符的一般工作原理,以及为什么如果我填充动态创建的数组会导致错误。

动态分配最多可以解除一次。因此,在析构函数中解除分配时,建立一个类不变量非常重要,该类不变量最多一个实例唯一拥有相同的指针。如果违反了这种不变性,则这些实例的析构函数可能会尝试两次delete相同的指针,从而导致未定义的行为。这很糟糕。

您的类确实orderedVector在其析构函数中解除分配。但是,类的(隐式生成的(复制构造函数复制成员变量,这违反了唯一所有权的类不变量。

您未能提供MCVE,但可以合理地猜测您的程序复制了orderedVector的实例,由于同一指针的多次delete而导致未定义的行为。

解决方案是使类不可复制和不可移动,或者遵循 3(或 5(规则,即以强制唯一所有权不变的方式实现复制(和移动(构造函数和赋值运算符。

相关内容

最新更新