C++ 尝试运行代码时,堆已损坏

C++ 尝试运行代码时,堆已损坏,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

当我运行我的程序时,它会中断,并且在调试程序时出现错误“堆已损坏”,实际上它会很好地完成整个过程,并在系统上中断(“暂停”),这似乎是一个奇怪的出错位置。我不知道问题在哪里。程序运行得很好,直到我为+和OS添加了操作符重载

下面是我的代码:

MAIN.CPP

#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;
}