gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-28 01:35:07 26 4
gpt4 key购买 nike

我正在尝试为我的 TurtleProgram 类创建一个重载的 + 运算符,它存储一个动态分配的字符串数组。但是方法返回的时候调用了析构函数,里面的delete操作抛出异常“Invalid address specified to RtlValidateHeap”。

下面是重载运算符定义、析构函数、默认构造函数、复制构造函数和重载运算符方法中使用的调整大小方法定义。

我已经对这个错误进行了研究,但我没能找到任何与我的问题相关的问题。

// 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);
}

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

最佳答案

主要问题是缺少复制构造函数(参见 rule of three)!

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

请注意,即使在像这样的表达式中

TurtleProgram x, y;
TurtleProgram z = x + y;

将调用复制(或移动,如果提供)构造函数而不是赋值运算符!

如果没有,默认情况下只提供复制指针,这将导致双重删除,因为 operator+ 中的临时对象和目标对象都持有相同的指针。

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

顺便说一下:如果您使用 std::vector,根据您目前提供的内容,您可以完全跳过构造函数、析构函数和赋值运算符。默认值将很适合,因为 std::vector 的构造函数/析构函数/赋值运算符随后将被调用,它们可以很好地完成您需要的工作。

关于效率的一些进一步问题和要点(仅供学习,如果您不切换到 std::vector):

任何分配给new的资源都必须是deleted,任何分配给new[]的资源都必须是delete[]d!如果你混合(像你一样),未定义的行为!!!

您在创建空数组时引入了内存泄漏:

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

但仅有条件地删除成员(已修复错误删除):

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

空数组存在,也占内存,任何情况下都需要删除该成员:

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

更好的是:

instructions_ = nullptr;
size_ = 0;

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

所以你根本不会为空海龟占用任何内存;你仍然不需要检查,删除空指针是绝对合法的(同时使用 deletedelete[])...

你绝对应该提供一个移动构造函数/赋值运算符(rule of five):

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_。将此留作您的练习。

关于c++ - 为什么我的重载 + 运算符在返回时会产生 "Invalid address specified to RtlValidateHeap"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49646114/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com