为什么我的重载 + 运算符在返回时会产生"Invalid address specified to RtlValidateHeap"错误?



我正在尝试为我的乌龟程序类创建一个超载 运算符,该类存储动态分配的字符串数组。但是,当该方法返回时,调用了驱动器,并且内部删除操作将带有"指定为rtlvalidateheap指定的无效地址"的异常。

以下是超载运算符定义,destuructor,默认构造函数,复制构造函数以及超载运算符方法中使用的调整大小方法定义。

我已经对错误进行了研究,但是我找不到与我有关的任何问题。

// overloaded + operator
// postconditions: returns a new TurtleProgram object that is the sum of two TurtleProgam instruction arrays
TurtleProgram TurtleProgram::operator+(const TurtleProgram &that)
{
    TurtleProgram returnTP;
    returnTP.resize(this->size_ + that.size_);
    for (int i = 0; i < this->size_ + that.size_; i++)
    {
        if (i < this->size_)
        {
            returnTP.instructions_[i] = this->instructions_[i];
        }
        else
        {
            returnTP.instructions_[i] = that.instructions_[i - this->size_];
        }
    }
    return(returnTP);
}
// resize: resized the array to be of a new size
// preconditions: the new size must be a positive integer
// postconditions: the array is resized, and size is updated
void TurtleProgram::resize(int newSize)
{
    string *temp = new string[newSize];
    // iterate through, transferring the contents from the old array to the resized array, then setting any empty spaces to ""
    for (int i = 0; i < newSize; i++)
    {
        if (i < size_)
        {
            temp[i] = instructions_[i];
        }
        else
        {
            temp[i] = "";
        }
    }
    if (size_ != 0)
    {
        delete instructions_;
    }
    instructions_ = temp;
    size_ = newSize;
}
// Default constructor: initializes as an empty array
// postconditions: a new TurtleProgram object is made with an empty array and a size of 0
TurtleProgram::TurtleProgram()
{
    instructions_ = new string[0];
    size_ = 0;
}
// Default destructor: deallocates instructions_ before destroying the object
// postconditions: the memory is released, and the object destroyed
TurtleProgram::~TurtleProgram()
{
    if (size_ != 0)
    {
        delete instructions_;
    }
}
TurtleProgram& TurtleProgram::operator=(const TurtleProgram &that)
{
    resize(that.getLength());
    for (int i = 0; i < size_; i++)
    {
        this->instructions_[i] = that.instructions_[i];
    }
    return(*this);
}

任何人都可以发现我在做错什么/不了解吗?在此先感谢您的任何帮助,并提前对任何发布错误。这是我的第一个问题!

主要问题是缺少复制构造函数(请参见三个规则(!

TurtleProgram::TurtleProgram(TurtleProgram const& that)
    : TurtleProgram()
{
    *this = that;
}

请注意,即使在

之类的表达中也
TurtleProgram x, y;
TurtleProgram z = x + y;

将调用副本(或移动(构造函数,而不是分配操作员!

没有一个,只需复制指针即可提供默认值,这将导致双重删除,因为operator+中的临时性和目标对象都保持相同的指针。

从我所看到的,您只是在重新实现std::vector已经提供的所有功能!您应该真正考虑使用它,而不是尝试(失败(重新发明轮子...

顺便说一句:如果您使用std :: vector,从到目前为止提供的内容,您只能完全跳过构造函数,击路仪和分配运算符。那时默认值将很好,因为std::vector的构造函数/destructor/tizement oberator将被调用,这可以很好地完成您需要的工作。

一些进一步的问题和效率的点(如果您不切换到std::vector,则只是用于学习(:

任何分配给new的资源都必须为delete D,任何分配给new[]的人都必须是delete[] D!如果您Intermix(像您一样(,不确定的行为 !!!

创建一个空数组时,您引入了内存泄漏:

instructions_ = new string[0];
size_ = 0;

,但仅有条件地删除成员(已经固定错误删除(:

if (size_ != 0)
{
    delete[] instructions_;
}

空数阵列也存在并占据内存,因此您需要在 ainy 案例中删除成员:

//if (size_ != 0)
//{
    delete[] instructions_;
//}

更好:

instructions_ = nullptr;
size_ = 0;
//if (size_ != 0)
//{
    delete[] instructions_;
//}

因此,您根本不会占据任何记忆来进行空乌龟;您仍然不需要检查,删除零指针绝对合法(使用deletedelete[](...

您绝对应该提供移动构造函数/分配运算符(五个规则(:

TurtleProgram::TurtleProgram(TurtleProgram&& that)
    : TurtleProgram()
{
    *this = std::move(that);
}
TurtleProgram& TurtleProgram::operator=(TurtleProgram&& that)
{
    using std::swap;
    swap(size_, that.size_);
    swap(instructions_, that.instructions_);
    return *this;
}

您可以节省大量的内存分配和初始化工作...

for (int i = 0; i < this->size_ + that.size_; i++)
{
    if (i < this->size_)
    {
        returnTP.instructions_[i] = this->instructions_[i];
    }
    else
    {
        returnTP.instructions_[i] = that.instructions_[i - this->size_];
    }
}

进行两个单独的循环:

for (int i = 0; i < this->size_; i++)
{
    returnTP.instructions_[i] = this->instructions_[i];
}
for (int i = this->size_; i < this->size_ + that.size_; i++)
{
    returnTP.instructions_[i] = that.instructions_[i - this->size_];
}

类似:

for (int i = 0; i < newSize; i++)
{
    if (i < size_)
    {
        temp[i] = instructions_[i];
    }
    else
    {
        temp[i] = "";
    }
}

它将得到:

for (int i = 0; i < size_; i++)
{
    temp[i] = instructions_[i];
}

嗯,第二部分???不必要的是,operator new[]已经调用任何数组元素的默认构造函数,无论如何都会创建空字符串...但是,一个点打开了:适用于newSize的合适处理小于size_。将其作为锻炼。

相关内容

  • 没有找到相关文章

最新更新