我正在尝试为我的乌龟程序类创建一个超载 运算符,该类存储动态分配的字符串数组。但是,当该方法返回时,调用了驱动器,并且内部删除操作将带有"指定为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_;
//}
因此,您根本不会占据任何记忆来进行空乌龟;您仍然不需要检查,删除零指针绝对合法(使用delete
和delete[]
(...
您绝对应该提供移动构造函数/分配运算符(五个规则(:
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_
。将其作为锻炼。