调试断言失败! C++ VS2012 - 模板 Class

Debug Assertion Failed! C++ VS2012 - Template Class

我正在做一个作业,我已经为 Vector 组合了一个模板 class,现在(根据作业)继承了它以使其成为可排序的。在 void SearchableVector<T>::add(T itemToAdd) 方法的最后它抛出一个 Debug Assertion Failed! 错误。错误全文如下:

---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Debug Assertion Failed!

Program: ...tudio 2012\Projects\COSC 1437\Program 10\Debug\Program 10.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgdel.cpp
Line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

---------------------------
Abort   Retry   Ignore   
---------------------------

我环顾四周,发现这是一个非常常见的错误,通常与内存管理有关。经常在不适当的事情上打电话给 delete。我一定是在做类似的事情,因为我收到了错误,但我找不到我做错了什么。如果您能帮我 and/or 指出正确的方向,我们将不胜感激。

Main.cpp

#include "SimpleVector.h"
#include "SearchableVector.h"
#include <stdlib.h>
#include <time.h>
void main()
{
        srand (time(NULL));
        SearchableVector<int> v(0);
        for (int i = 0; i < 20; i++)
        {
            v.add(rand() % 20);
        }
        v.print();
}

SimpleVector.h

#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
#include <iostream>
#include <stdexcept>
#include <iomanip>
using namespace std;

template<class T>
class SimpleVector {
public:
    //Constructors
    SimpleVector();   //default constructor, size 0
    SimpleVector(int); //parameterized constructor with default size
    SimpleVector(const SimpleVector& a); //copy constructor
    ~SimpleVector(); //destructor

    T& operator[](int) const;
    SimpleVector<T>& operator=(SimpleVector<T>);
    const bool operator==(SimpleVector&) const;
    void push_back(T);
    T& pop_back();
    T& getElement(int);
    int getSize() const;
    void print() const;
protected:
    int size;
    T* internalArray;
    void SimpleVector<T>::swap(SimpleVector&);
};
template<class T>
SimpleVector<T>::SimpleVector()
{
    size = 0;
    internalArray = nullptr;
}

template<class T>
SimpleVector<T>::SimpleVector(int sizeOfArray) 
{
    if (sizeOfArray < 0) throw "SimpleVector size must not be less than 0";
    internalArray = new T[sizeOfArray]();
    size = sizeOfArray;
}

template<class T>
SimpleVector<T>::SimpleVector(const SimpleVector& vectorToCopy):size(vectorToCopy.getSize()), internalArray( new T[vectorToCopy.getSize()] )
{
    for (int i = 0; i < size; i++)
        internalArray[i] = vectorToCopy.internalArray[i];
}
template<class T>
SimpleVector<T>::~SimpleVector() {
    //cout << "Destructor called" << std::endl;
    delete[] internalArray;
}

template<class T>
T& SimpleVector<T>::operator[](int i) const {
    if (i<0 || i>=size) throw "Vector::operator[] : index is out of range";
    return internalArray[i];
}

template<class T>
SimpleVector<T>& SimpleVector<T>::operator=(SimpleVector<T> rightSide) { 
    rightSide.swap(*this);
    return *this;
}

template<class T>
const bool SimpleVector<T>::operator==(SimpleVector& right) const {
    if (size() != right.size())
        return false;
    else {
        for (int i = 0; i < size(); i++){
            if (internalArray[i] != right[i])
                return false;
        }
    }
    return true;
}

template<class T>
void SimpleVector<T>::push_back(T itemToAdd) {
    SimpleVector<T> temp(size + 1);
    for (int i = 0; i < size; i++)
        temp[i] = internalArray[i];
    temp[size] = itemToAdd;
    temp.swap(*this);
}

template<class T>
T& SimpleVector<T>::pop_back()
{
    SimpleVector<T> temp(size - 1);
    for (int i = 0; i < size; i++)
        temp[i] = internalArray[i];
    T pop = internalArray[size-a];
    temp.swap(*this);
    return pop;
}

template<class T>
T& SimpleVector<T>::getElement(int indexToGet)
{
    return internalArray[indexToGet];
}

template<class T>
int SimpleVector<T>::getSize() const {
    return this->size; 
}

template<class T>
void SimpleVector<T>::print() const
{
    for (int i = 0; i < size; i++)
    {
        std::cout << internalArray[i];
        if (i!=(size-1))
            std::cout << ",";
        else
            std::cout << std::endl;
        if (i%10 == 0 && i!=0)
            std::cout <<std::endl;
    }
}

template<class T>
void SimpleVector<T>::swap(SimpleVector& other)
{
     std::swap(internalArray, other.internalArray);
     std::swap(size, other.size);
}
#endif

SearchableVector.h

#ifndef SEARCHABLEVECTOR_H
#define SEARCHABLEVECTOR_H
#include "SimpleVector.h"
template<class T>
class SearchableVector : protected SimpleVector<T>
{
public:
    SearchableVector(int);
    SearchableVector(const SearchableVector&);
    ~SearchableVector();
    void add(T);
    T getElement(int);
    int getSize() const;
    void print() const;
    int search(T);
};
template<class T>
SearchableVector<T>::SearchableVector(int sizeOfArray) : SimpleVector(sizeOfArray)
{

}

template<class T>
SearchableVector<T>::SearchableVector(const SearchableVector& vectorToCopy) : SimpleVector(vectorToCopy)
{

}

template<class T>
SearchableVector<T>::~SearchableVector()
{
    delete[] internalArray;
}

template<class T>
void SearchableVector<T>::add(T itemToAdd)
{
    bool flag = false;
    SearchableVector<T> temp(size + 1);
    for (int i = 0; i < size; i++)
    {
        if ((itemToAdd <= internalArray[i]) && (flag == false))
        {
            temp[i] = itemToAdd;
            i++;
            flag = true;
        }
        temp[i] = internalArray[i];
    }
    if (flag == false)
        temp[size] = itemToAdd;
    temp.swap(*this);
} // !*******************! THROWS THE ERROR RIGHT HERE !*******************! 

template<class T>
T SearchableVector<T>::getElement(int elementToGet)
{
    return SimpleVector::getElement(elementToGet);
}

template<class T>
int SearchableVector<T>::getSize() const
{
    return SimpleVector::getSize();
}

template<class T>
void SearchableVector<T>::print() const 
{
    SimpleVector::print();
}

template<class T>
int SearchableVector<T>::search(T itemToSearchFor)
{

}

#endif

首先,在使用继承的时候,99%的时候应该使用虚析构函数。

这很重要。

virtual ~SimpleVector();

当删除一个对象时,它的基础 class 析构函数也会被调用。
在您的情况下,两个析构函数中都有 delete[] internalArray;
把删除留在基class,因为那个成员属于它,它应该处理它。

下次遇到类似情况时,在该对象类型的所有 delete 调用附近放置一个断点,然后您就可以看到调用了哪些以及调用的顺序。