C ++对此的解释删除[]错误? [英] C++ Explanation for this delete[] Error?

查看:157
本文介绍了C ++对此的解释删除[]错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

做了很大的改动,以项目后,我创建了我花了相当长的一段追踪到错误。

After making a lot of changes to a project, I created an error that took me quite a while to track down.

我有一个包含一个动态分配的数组的类。然后,我创建这个类的一个动态数组。那么我可以删除[]数组。但是,如果我删除之前数组中替换项目时,它会导致错误。在调试模式下,它给出了一个dbgdel.cpp断言消息前pression:_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)。这里是一个小程序来演示。

I have a class which contains a dynamically allocated array. I then create a dynamic array of this class. I can then delete[] that array. But, if I replace an item in the array before deleting it, it causes an error. In debug mode, it gives an assertion message from dbgdel.cpp "Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)". Here is a small program to demonstrate.

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

我很好奇,为什么会这样?当数组中的项目被替换,它的析构函数被调用。然后将新的项目中从阵列分离的位置分配它的数据。然后删除[]调用数组中的所有对象的析构函数。当析构函数被调用,就应该删除的项目的数据数组。我无法想象的是什么问题,但我想,如果有人可以解释的。

I'm curious, why does this happen? When the item in the array gets replaced, its destructor gets called. Then the new item allocates its data in a location separate from the array. Then delete[] calls the destructors of all the objects in the array. When the destructors get called, they should delete the item's data array. I can't imagine what the problem is, but I'd like if someone could explain.

推荐答案

您的类被打破:它有一个不平凡的析构函数,但是你没有定义拷贝构造函数和拷贝赋值操作符。这意味着该类不能正确地复制或分配到(因为破坏的状态不是复制或适当分配的),因为你是在你的例子code注意到。

Your class is broken: It has a non-trivial destructor, but you do not define copy constructors and copy assignment operators. That means that the class cannot be correctly copied or assigned-to (since the destructible state is not copied or assigned appropriately), as you are noticing in your example code.

您可以让你的类的不可复制的(在这种情况下,您的code将无法编译了),或的举动,只有的,在这种情况下,你需要定义移动建设和布展任务,或者正确拷贝的通过实现数据的深层副本。

You can either make your class uncopiable (in which case your code won't compile any more), or move-only, in which case you need to define move construction and move-assignment, or properly copyable by implementing a deep copy of the data.

下面是如何,添加以下定义:

Here's how, add the following definitions:

不可复制:

SomeClass(SomeClass const &) = delete;
SomeClass & operator(SomeClass const &) = delete;

可移动只:

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

可复制:

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

其结果是,析构函数的性质决定了类的不变量,因为每一个对象必须是一致的破坏。从这个可以推断副本所需的语义和移动操作。 (这通常被称为三或五规则的规则。)

The upshot is that the nature of the destructor determines the invariants of the class, because every object must be consistently destructible. From that you can infer the required semantics of the copy and move operations. (This is often called the Rule of Three or Rule of Five.)

这篇关于C ++对此的解释删除[]错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆