C++ 尝试运行代码时,堆已损坏
当我运行我的程序时,它会中断,并且在调试程序时出现错误“堆已损坏”,实际上它会很好地完成整个过程,并在系统上中断(“暂停”),这似乎是一个奇怪的出错位置。我不知道问题在哪里。程序运行得很好,直到我为+和OS添加了操作符重载 下面是我的代码: MAIN.CPPC++ 尝试运行代码时,堆已损坏,c++,arrays,operator-overloading,C++,Arrays,Operator Overloading,当我运行我的程序时,它会中断,并且在调试程序时出现错误“堆已损坏”,实际上它会很好地完成整个过程,并在系统上中断(“暂停”),这似乎是一个奇怪的出错位置。我不知道问题在哪里。程序运行得很好,直到我为+和OS添加了操作符重载 下面是我的代码: MAIN.CPP #include "stdafx.h" #include "vector.h" // the printV function // used to test the copy constructor // parameter: a MyV
#include "stdafx.h"
#include "vector.h"
// the printV function
// used to test the copy constructor
// parameter: a MyVector object
void printV(Vector);
int main()
{
cout << "\nCreating a vector Sam of size 4.";
Vector sam(4);
cout << "\nPush 12 values into the vector.";
for (int i = 0; i < 12; i++)
sam.push_back(i);
cout << "\nHere is sam: ";
cout << sam;
cout << "\n---------------\n";
cout << "\nCreating a vector Joe of size 4.";
Vector joe(4);
cout << "\nPush 6 values into the vector.";
for (int i = 0; i < 6; i++)
joe.push_back(i * 3);
cout << "\nHere is joe: ";
cout << joe;
cout << "\n---------------\n";
cout << "\nTest the overloaded assignment operator \"joe = sam\": ";
joe = sam;
cout << "\nHere is sam: ";
cout << sam;
cout << "\n---------------\n";
cout << "\nHere is joe: ";
cout << joe;
cout << "\n---------------\n";
// pass a copy of sam by value
printV(sam);
system("PAUSE");
return 0;
}
void printV(Vector v)
{
cout << "\n--------------------\n";
cout << "Printing a copy of a vector\n";
cout << v;
}
#include "stdafx.h"
#include "vector.h"
Vector::Vector()
{
vectorSize = 0;
vectorCapacity = 0;
vectorArray = 0;
}
// Create new array with given capacity
Vector::Vector(int n)
{
vectorCapacity = n;
vectorArray = new int[vectorCapacity];
}
//Return array size
int Vector::size()
{
return vectorSize;
}
// Return array capacity
int Vector::capacity()
{
return vectorCapacity;
}
// clear array values
void Vector::clear()
{
for (int i = 0; i < sizeof(vectorArray); i++)
{
vectorArray[i] = '\0';
}
vectorSize = 0;
vectorCapacity = 2;
}
// Add number to array and double array size if needed
void Vector::push_back(int n)
{
int test = 100;
if (vectorCapacity > vectorSize)
{
vectorArray[vectorSize] = n;
vectorSize++;
}
else {
if (vectorCapacity == 0) {
vectorArray = new int[4];
vectorArray[0] = n;
vectorCapacity = 4;
vectorSize++;
}
else {
int newCapacity = vectorCapacity * 2;
// Dynamically allocate a new array of integers what is somewhat larger than the existing array.An algorithm that is often used is to double the size of the array.
int *tempArray = new int[newCapacity];
// Change capacity to be the capacity of the new array.
vectorCapacity = newCapacity;
// Copy all of the numbers from the first array into the second, in sequence.
for (int i = 0; i < Vector::size(); i++)
{
tempArray[i] = vectorArray[i];
}
delete[] vectorArray;
vectorArray = new int[newCapacity];
for (int i = 0; i < Vector::size(); i++)
{
vectorArray[i] = tempArray[i];
}
delete[] tempArray;
// Add the new element at the next open slot in the new array.
vectorArray[vectorSize] = n;
// Increment the size;
vectorSize++;
}
}
}
// Return Value and given point in array
int Vector::at(int n)
{
return vectorArray[n];
}
// Cout Vector
ostream& operator<<(ostream& os, Vector vt)
{
int size = vt.size();
for (int i = 0; i < size; i++) {
os << "index " << i << " is " << vt.at(i) << endl;
}
return os;
}
// Set one vector to equil another
Vector Vector::operator=(Vector& right) {
// Clear array on left
for (int i = 0; i < sizeof(vectorArray); i++)
{
vectorArray[i] = '\0';
}
vectorSize = right.size();
vectorCapacity = right.size() * 2;
// Assign values from left to right
for (int i = 0; i < vectorSize; i++)
{
vectorArray[i] = right.at(i);
}
return vectorArray[0];
}
#包括“stdafx.h”
#包括“vector.h”
//printV函数
//用于测试复制构造函数
//参数:MyVector对象
void printV(向量);
int main()
{
cout有很多错误,但导致所述症状的是运算符=
从未为矢量数组分配新的int
数组
每次使用sizeof(vectorray)
都是错误的。这只是指针的大小,而不是指向的区域的分配
每一个做向量数组[i]='\0';
的地方充其量都是毫无意义的,不管是什么意图,这都是错误的做法。足够了,我甚至猜不出意图
在clear
函数中,唯一必要的步骤是vectorSize=0;
其余步骤充其量是没有意义的。将容量设置为2很奇怪,尽管它不会造成重大伤害
operator=
应该有返回类型Vector&
而不是Vector
,并且应该返回*这个不能构造一个向量
,它的容量是旧向量的一个值。一般来说,一个类的几乎所有operator=
成员都应该返回*这个。该规则的例外情况如下超出您当前尝试学习的级别。问题在于操作符=()
为什么?
您从容量为4的sam开始。您将其中的12项向后推。当您到达第5个元素时,容量将从4倍增加到8倍。然后您到达第9个元素,容量将增加到24
然后你有一个初始容量为4的joe
。你向后推6个项目。当你到达第5个元素时,它的容量增加到8个
然后执行joe=sam
时,运算符会覆盖joe
的大小和容量,但不会验证容量是否匹配,也不会分配丢失的容量。当您尝试在实际上只有8个容量的向量中复制12个元素时,会对内存造成一些附带损害,并损坏堆
解决方案
不要盲目覆盖容量。如果容量足够,请保留容量。如果容量不足,请对齐容量并重新分配
// Set one vector to equal another
Vector Vector::operator=(Vector& right) {
//...
if (vectorCapacity < right.vectorCapacity) {
delete[] vectorArray; // assuming pointer is either nullptr or valid array
vectorArray = new int[right.vectorCapacity];
vectorCapacity = right.vectorCapacity;
}
vectorSize = right.size();
// Assign values from left to right
//...
return *this;
}
//将一个向量设置为等于另一个向量
向量:运算符=(向量和右){
//...
if(向量容量<右向量容量){
delete[]vectorArray;//假设指针为nullptr或有效数组
vectorArray=新整数[right.vectorCapacity];
向量容量=右。向量容量;
}
vectorSize=right.size();
//从左到右赋值
//...
归还*这个;
}
请注意,最好通过引用返回向量!鉴于到目前为止的所有答案,另一个问题是您未能实现用户定义的复制构造函数:
Vector(const Vector& n);
必须正确实现此函数,因为您有按值返回向量的函数。由于未实现此函数,复制将无法正常工作
第二个问题是,应该通过引用而不是通过操作符=
函数中的值来返回向量
我的第一个建议是使用操作符=
中现有的任何代码,并在复制构造函数中执行“真实”复制。下面是复制构造函数的简化版本:
#include <algorithm>
//..
Vector::Vector(const Vector& rhs) : vectorCapacity(rhs.vectorCapacity),
vectorArray(new int[rhs.vectorCapacity]),
vectorSize(rhs.size())
{
std::copy(rhs.vectorArray, rhs.vectorArray + rhs.vectorCapacity, vectorArray);
}
然后使用copy/swap
操作operator=
变得非常简单
#include <algorithm>
//...
Vector& operator=(const Vector& v)
{
Vector temp = v;
swap(this.vectorCapacity, temp.vectorCapacity);
swap(this.vectorArray, temp.vectorArray);
swap(this.vectorSize, temp.vectorSize);
return *this;
}
#include和。我认为可能是Vector.cpp for=…上的运算符重载函数不确定原因。例如,sizeof(vectorray)
是指针的大小。然后您实际使用了正确的一个:vectorSize
。但是整个清除过程甚至不应该完成?您不应该重新分配内容吗?还有返回vectorArray[0]
,它将隐式转换为Vector
调用Vector(int n)
所以在我的脑海中,这就是我一直在想的,我想你说的,很多时候我想我做了。从一开始,我清除了左边的当前向量,我们将分配右边的值。然后我将左边数组的大小更改为右边数组的大小,更改左边数组的容量o 2乘以右边的数组,这样就有了添加的空间。然后我从左到右插入数组中的值。它有一个错误,我必须返回一个向量,所以我把返回值放在那里,即使我知道它与此无关。if
保护delete[]
是毫无意义的。如果vectorCapacity
和vectorray
保持一致(因此两者都为零或都不为零),则测试不是“错误”,只是没有用处。但是如果测试有任何效果,则该效果将是错误的。delete[]
正确地处理空指针。我认为意图模式会说this->vectorCapacity
应该从right.size()
计算,而不是从right.vectorCapacity
计算。这不是严重的“错误”按照之前的方式设置它,但这不仅是低劣的设计,而且与代码其余部分显示的意图相反。谢谢,我让它工作了……现在当我在类上添加解构器时,调用delete[]vectorray时,它有一个错误;现在,当我移除解构器时,它很好。你知道为什么吗?@BrandonTurpy是正确的术语
Vector::~Vector()
{ delete [] vectorArray; }
#include <algorithm>
//...
Vector& operator=(const Vector& v)
{
Vector temp = v;
swap(this.vectorCapacity, temp.vectorCapacity);
swap(this.vectorArray, temp.vectorArray);
swap(this.vectorSize, temp.vectorSize);
return *this;
}