自定义向量中的堆损坏错误 class

Heap corruption error in custom vector class

我在编写的代码中收到运行时错误。当我调用 grow() 函数时,它运行良好,直到它到达 delete,然后它崩溃并显示:

这让我很困惑,我不明白这是怎么回事。

这是我的代码发生的地方:

.cpp 文件

#include "MyVector.h"
#include <cstdlib>;
void MyVector::grow()
{

    if (cap == 0)
        cap = MINCAP;
    else
        cap = cap*MINCAP;
    int* temp = new int[cap];

    for (int i = 0; i < vectorSize; i++)
    {
        temp [i] = theVector[i];
    }
    for (int i = vectorSize; i < cap; i++)
    {
        temp[i] = 0;
    }
    delete[] theVector;
    theVector = temp;

}

MyVector::MyVector()
{
    clear();
}

MyVector::~MyVector()
{
    delete[] this->theVector;

}

MyVector::MyVector(int _cap)
{
    cap = _cap;
    for (int i = 0; i < cap; i++)
    {
        this->theVector[i] = 0;
    }
}

MyVector::MyVector(const MyVector & vect)
{
    this->vectorSize = vect.vectorSize;
    this->cap = vect.cap;
    delete[] theVector;
    theVector = new int[cap];
    for (int i = 0; i < vectorSize; i++)
    {
        this->theVector[i] = vect.theVector[i];
    }
    for (int i = vectorSize; i < cap; i++)
    {
        this->theVector[i] = 0;
    }
}

int MyVector::size() const
{
    return vectorSize;
}

int MyVector::capacity() const
{
    return cap;
}

void MyVector::clear()
{
    vectorSize = 0;
    cap = MINCAP;
    delete[] theVector;
    theVector = new int[MINCAP];
    for (int i = 0; i <MINCAP; i++)
    {
        *(theVector + i) = 0;
    }
}
//Put an int into the vector
void MyVector::push_back(int n)
{
    if (theVector == nullptr)
        clear();
    if (vectorSize+1 >= cap) 
    {
        grow();
        theVector[vectorSize] = n;
        vectorSize++;
    }
    else 
    {
        theVector[vectorSize] = n;
        vectorSize++;
    }

}

int MyVector::at(int _location)
{
    if (_location < 0 || _location >= vectorSize)
        throw _location;

    return theVector[_location];
}

MyVector & MyVector::operator=(const MyVector & rho)
{
    // test for self assignment
    if (this == &rho)
        return *this;

    // clean up array in left hand object (this)
    delete[] this->theVector;

    // create a new array big enough to hold right hand object's data
    this->vectorSize = rho.size();
    this->cap = rho.cap;
    this->theVector = new int[cap];
    // copy the data
    for (int i = 0; i < vectorSize; i++)
    {
        this->theVector[i] = rho.theVector[i];
    }
    for (int i = vectorSize; i < cap; i++)
    {
        this->theVector[i] = 0;
    }
    // return this object
    return *this;
}

The.h 文件

#pragma once
#include <array>
#include <fstream>
using namespace std;
class MyVector
{
private:
    //the minimum capacity of the vector
    const int MINCAP = 2;
    //the amount of items in the vector
    int vectorSize = 0;
    //the maximum ammount of items in the vector
    int cap = MINCAP;
    //The pointer to the first integer in the vector
    int* theVector = new int[MINCAP];
    //The grow function
    //Parameters : none
    //returns : none
    void grow();
public:
    //The nonparmeterized constructor
    //Parameters : none
    //returns :none
    MyVector();
    //The deconstructor
    //Parameters : none
    //returns : none
    ~MyVector();
    // The parameterized constructor
    //Parameters : the capacity to set it to
    //returns : none
    MyVector(int _cap);
    //Get the size
    //Parameters : none
    //returns : the size
    MyVector(const MyVector& vect);
    //Get the size
    //Parameters : none
    //returns : the size
    int size() const;
    //get the capacity 
    //Parameters : none
    //returns : cap
    int capacity() const;
    //clear the data
    //Parameters : none
    //returns :none
    void clear();
    //insert an int into the vector
    //Parameters : the int
    //returns : none
    void push_back(int n);
    //gets the int at a location
    //Parameters : the location
    //returns : the integer
    int at(int _location);
    //Overload the = operator
    //Parameters : the one to copy
    //returns : the vector
    MyVector& operator=(const MyVector& rho);
    //Overload the << operator
    //Parameters : the one to copy
    //returns : the vector
    friend ostream& operator<<(ostream& os, MyVector& TheVector)
    {
        for (int i = 0; i < TheVector.size(); i++)
        {
            os << TheVector.at(i) << ", ";
        }

        return os;
    }



};

驱动来测试一下。

#include <iostream>
#include "MyVector.h"     
using namespace std;

// the printV function
// used to test the copy constructor
// parameter: a MyVector object
void printV(MyVector);

int main()
{
    cout << "\nCreating a vector Sam of size 4.";
    MyVector 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.";
    MyVector 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);


    cout << endl;
    system("PAUSE");
    return 0;
}

void printV(MyVector v)
{
    cout << "\n--------------------\n";
    cout << "Printing a copy of a vector\n";
    cout << v;
}

编辑:我根据建议更新了代码。

您的代码存在一些问题:

  1. 您的 MyVector(int) 构造函数没有分配请求数量的数组元素。它甚至根本没有触及 theVector,因此 theVector 被成员初始化为默认的 MINCAP 元素,即使请求的 cap 实际上更高。

  2. 您的 MyVector(MyVector&) 复制构造函数声明错误。要成为一个合适的复制构造函数,它需要通过 const 引用来获取输入对象。没有它,您就没有合适的复制构造函数。如果编译器生成自己的默认复制构造函数,它只会将您的 theVector 指针从一个对象复制到另一个对象,而不是实际创建数组数据的新副本,从而导致所有权问题。

  3. 例如,您的 printV() 函数接受一个输入 MyVector by value,它复制构造一个临时对象。当临时对象超出范围并在其 theVector 指针上调用 delete[] 时,如果使用编译器的默认复制构造函数,它实际上将破坏原始 MyVector 对象中的数组。你需要一个合适的复制构造函数。

  4. clear() 正在使用 delete 而不是 delete[]。使用 new 分配的内存必须 使用 delete 释放。使用 new[] 分配的内存必须 使用 delete[] 释放。它们不匹配会导致内存问题。

话虽如此,我建议执行以下操作:

#pragma once
#include <iostream>

class MyVector
{
private:
    //the minimum capacity of the vector
    const int MINCAP = 2;

    //the number of items in the vector
    int vectorSize = 0;

    //the maximum number of items in the vector
    int cap = 0;

    //The pointer to the first integer in the vector
    int* theVector = nullptr;

    //The grow function
    //Parameters : none
    //returns : none
    void grow();

public:
    //The nonparmeterized constructor
    //Parameters : none
    //returns :none
    MyVector();

    // The parameterized constructor
    //Parameters : the capacity to set it to
    //returns : none
    MyVector(int _cap);

    // The copy constructor
    //Parameters : the vector to copy from
    //returns : none
    MyVector(const MyVector& src);

    // The move constructor
    //Parameters : the vector to move from
    //returns : none
    MyVector(MyVector&& src);

    //The destructor
    //Parameters : none
    //returns : none
    ~MyVector();

    //Get the size
    //Parameters : none
    //returns : the size
    int size() const;

    //get the capacity 
    //Parameters : none
    //returns : cap
    int capacity() const;

    //clear the data
    //Parameters : none
    //returns :none
    void clear();

    //insert an int into the vector
    //Parameters : the int
    //returns : none
    void push_back(int n);

    //gets the int at a location
    //Parameters : the location
    //returns : the integer
    int at(int _location);

    //swap the content of a vector with another
    //Parameters : the vector to swap with
    //returns : none
    void swap(MyVector& other);

    //Overload the copy = operator
    //Parameters : the one to copy from
    //returns : the vector
    MyVector& operator=(const MyVector &rho);

    //Overload the move = operator
    //Parameters : the one to move from
    //returns : the vector
    MyVector& operator=(MyVector && rho);

    //Overload the << operator
    //Parameters : the one to print
    //returns : the stream
    friend std::ostream& operator<<(std::ostream& os, const MyVector& rho);
};

std::ostream& operator<<(std::ostream& os, const MyVector& rho);

void swap(MyVector &v1, MyVector &v2) { v1.swap(v2); }

namespace std {
    template <>
    void swap(MyVector &v1, MyVector &v2)
    {
            v1.swap(v2);
    }
}

#include "MyVector.h"
#include <algorithm>
#include <utility>

MyVector::MyVector()
    : MyVector(MINCAP)
{
}

MyVector::MyVector(int _cap)
    : theVector(new int[_cap]), cap(_cap)
{
    std::fill_n(theVector, cap, 0);
}

MyVector::MyVector(const MyVector & src)
    : theVector(new int[src.cap]), cap(src.cap), vectorSize(src.vectorSize)
{
    std::copy_n(src.theVector, vectorSize, theVector);
    std::fill_n(theVector+vectorSize, cap-vectorSize, 0);
}

MyVector::MyVector(MyVector && src)
{
    src.swap(*this);
}

MyVector::~MyVector()
{
    delete[] theVector;
}

void MyVector::grow()
{
    int newcap = cap;
    if (newcap == 0)
        newcap = MINCAP;
    else
        newcap = newcap * MINCAP;

    int* newVector = new int[newcap];

    std::copy_n(theVector, vectorSize, newVector);
    std::fill_n(newVector+vectorSize, newcap-vectorSize, 0);

    delete[] theVector;
    theVector = newVector;
    cap = newcap;
}

int MyVector::size() const
{
    return vectorSize;
}

int MyVector::capacity() const
{
    return cap;
}

void MyVector::clear()
{
    *this = MyVector();
}

void MyVector::push_back(int n)
{
    if (vectorSize >= cap) 
        grow();

    theVector[vectorSize] = n;
    ++vectorSize;
}

int MyVector::at(int _location)
{
    if ((_location < 0) || (_location >= vectorSize))
        throw _location;

    return theVector[_location];
}

void MyVector::swap(MyVector& other)
{
    std::swap(theVector, other.theVector);
    std::swap(cap, other.cap);
    std::swap(vectorSize, other.vectorSize);
}

MyVector& MyVector::operator=(const MyVector &rho)
{
    if (this != &rho)
    {
        int newcap = rho.cap;
        if (cap != newcap)
        { 
            delete[] theVector;
            theVector = nullptr;
            cap = 0;
            vectorSize = 0;

            theVector = new int[newcap];
            cap = newcap;
        }

        int newsize = rho.vectorSize;
        std::copy_n(rho.theVector, newsize, theVector);
        std::fill_n(theVector+newsize, cap-newsize, 0);
        vectorSize = newsize;
    }

    return *this;
}

MyVector& MyVector::operator=(MyVector && rho)
{
    rho.swap(*this);

    return *this;
}

std::ostream& operator<<(std::ostream& os, const MyVector& rho)
{
    os << "size " << rho.vectorSize << ", capacity " << rho.cap;
    if (rho.vectorSize > 0)
    {
        os << "\n" << rho.theVector[0];
        for (int i = 1; i < rho.vectorSize; ++i)
        {
            os << ", " << rho.theVector[i];
        }
    }

    return os;
}

#include <iostream>
#include "MyVector.h"     

// the printV function
// used to test the copy constructor
// parameter: a MyVector object
void printV(MyVector);

int main()
{
    std::cout << "\nCreating a vector Sam of capacity 4.";
    MyVector sam(4);

    std::cout << "\nPush 12 values into the vector.";
    for (int i = 0; i < 12; ++i)
        sam.push_back(i);

    std::cout << "\nHere is sam: ";
    std::cout << sam;
    std::cout << "\n---------------\n";

    std::cout << "\nCreating a vector Joe of capacity 4.";
    MyVector joe(4);

    std::cout << "\nPush 6 values into the vector.";
    for (int i = 0; i < 6; ++i)
        joe.push_back(i * 3);

    std::cout << "\nHere is joe: ";
    std::cout << joe;
    std::cout << "\n---------------\n";

    std::cout << "\nTest the overloaded copy assignment operator \"joe = sam\": ";
    joe = sam;

    std::cout << "\nHere is sam: ";
    std::cout << sam;
    std::cout << "\n---------------\n";

    std::cout << "\nHere is joe: ";
    std::cout << joe;
    std::cout << "\n---------------\n";

    std::cout << "\nTest the overloaded move assignment operator \"joe = MyVector(5)\": ";
    joe = MyVector(5);

    std::cout << "\nHere is joe: ";
    std::cout << joe;
    std::cout << "\n---------------\n";

    // pass a copy of sam by value
    printV(sam);

    std::cout << std::endl;

    system("PAUSE");
    return 0;
}

void printV(MyVector v)
{
    cout << "\n--------------------\n";
    cout << "Printing a copy of a vector\n";
    cout << v;
}