C++解释此删除[]错误?

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 []调用数组中所有对象的析构函数.当析构函数被调用时,它们应该删除项目的数据数组.我无法想象问题是什么,但我想如果有人能解释的话.

Ker*_* SB 9

你的类坏了:它有一个非平凡的析构函数,但你没有定义复制构造函数和复制赋值运算符.这意味着无法正确复制或分配类(因为不会复制或分配适当的可破坏状态),正如您在示例代码中注意到的那样.

您可以使您的类不可操作(在这种情况下您的代码将不再编译),或者仅移动,在这种情况下,您需要定义移动构造和移动分配,或通过实现深层副本来正确复制数据.

这是如何添加以下定义:

不可复制的:

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)

结果是析构函数的性质决定了类的不变量,因为每个对象必须始终是可破坏的.从中可以推断出复制和移动操作所需的语义.(这通常被称为三法则或五法则.)

  • 对; 规范有用的链接是[*什么是三个规则?*](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). (6认同)

Avt*_*Avt 5

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第二次释放.