Jan*_*ott 8 c++ arrays dynamic delete-operator
在对项目进行了大量更改后,我创建了一个错误,我花了很长时间才追查.
我有一个包含动态分配数组的类.然后我创建了这个类的动态数组.然后我可以删除[]那个数组.但是,如果我在删除它之前替换数组中的项目,则会导致错误.在调试模式下,它提供了一个断言消息从dbgdel.cpp"表达式:_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)".这是一个小程序来演示.
class SomeClass {
public:
int *data;
SomeClass() {
data = nullptr;
}
SomeClass(int num) {
data = new int[num];
}
~SomeClass() {
if (data != nullptr) {
delete[] data;
}
}
};
int main(int argc, char *args[]) {
SomeClass *someArray = new SomeClass[10];
//If you comment this out, there is no error. Error gets thrown when deleting
someArray[0] = SomeClass(10);
delete[] someArray;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我很好奇,为什么会这样?当替换数组中的项时,将调用其析构函数.然后,新项目将数据分配在与数组不同的位置.然后delete []调用数组中所有对象的析构函数.当析构函数被调用时,它们应该删除项目的数据数组.我无法想象问题是什么,但我想如果有人能解释的话.
你的类坏了:它有一个非平凡的析构函数,但你没有定义复制构造函数和复制赋值运算符.这意味着无法正确复制或分配类(因为不会复制或分配适当的可破坏状态),正如您在示例代码中注意到的那样.
您可以使您的类不可操作(在这种情况下您的代码将不再编译),或者仅移动,在这种情况下,您需要定义移动构造和移动分配,或通过实现深层副本来正确复制数据.
这是如何添加以下定义:
不可复制的:
SomeClass(SomeClass const &) = delete;
SomeClass & operator(SomeClass const &) = delete;
Run Code Online (Sandbox Code Playgroud)
活动只:
SomeClass(SomeClass const &) = delete;
SomeClass(SomeClass && rhs) : data(rhs.data) { rhs.data = nullptr; }
SomeClass & operator(SomeClass const &) = delete;
SomeClass & operator(SomeClass && rhs) {
if (this != &rhs) { delete data; data = rhs.data; rhs.data = nullptr; }
return *this;
}
Run Code Online (Sandbox Code Playgroud)
可复制:
SomeClass(SomeClass const & rhs) : ptr(new int[rhs->GetSizeMagically()]) {
/* copy from rhs.data to data */
}
SomeClass & operator(SomeClass const & rhs) {
if (this == &rhs) return *this;
int * tmp = new int[rhs->GetSizeMagically()];
/* copy data */
delete data;
data = tmp;
}
// move operations as above
Run Code Online (Sandbox Code Playgroud)
结果是析构函数的性质决定了类的不变量,因为每个对象必须始终是可破坏的.从中可以推断出复制和移动操作所需的语义.(这通常被称为三法则或五法则.)
Kerrek SB的答案很棒.我只是想澄清一下,在你的代码中,内存被释放了两次.
这段代码
someArray[0] = SomeClass(10);
Run Code Online (Sandbox Code Playgroud)
与此相同
SomeClass temp(10);
someArray[0] = temp; //here temp.data is copied to someArray[0].data
Run Code Online (Sandbox Code Playgroud)
然后〜为SomeClass()调用temp并data
首次释放.
这里
delete[] someArray;
Run Code Online (Sandbox Code Playgroud)
〜someClass()被调用someArray [0]并被data
第二次释放.
归档时间: |
|
查看次数: |
1649 次 |
最近记录: |