动态数组删除

时间:2015-03-18 10:34:02

标签: c++ arrays destructor

我正在使用动态数组,而且我遇到了问题。编译器为第一个数组(长度为1)调用析构函数两次。所以程序崩溃了。我很乐意得到任何帮助。谢谢。

class MyClass{
public:
    int *a;
    MyClass(int i){
        a = new int[i];
    }
    ~MyClass(){
        if (a) delete[]a;
    }
};


int main(){ 
    MyClass c(1);
    c = MyClass(2);
}

3 个答案:

答案 0 :(得分:3)

程序崩溃,因为复制MyClass仅复制指针成员,而不创建新数组,然后可以将其删除。因此,您删除两次相同的数组,即Undefined Behavior。

最好的解决方法是使用std::vector<int>而不是原始数组,如果每个实例都应该有自己的数组。

如果您(为了某些人为限制,没有实际的用例)需要使用原始数组,请定义合适的复制构造函数和赋值运算符。请参阅"The rule of Three"

答案 1 :(得分:1)

为什么要复制MyClass实例,调用默认生成器复制构造函数。这只会复制内部a指针,而不会创建新的int数组。

因此,当副本被销毁时,它delete是数组,然后当原始文件被销毁时,它也是delete的数组。

有两种解决方法:

  1. 优先:使用包含所有分配和复制功能的内容,例如std::vector(规则为0,我们将在一分钟内完成此操作),或者如果你想创建这样一个课程,比如教育兴趣,
  2. 遵循"rule of 5"(过去是3,在C ++ 11引入移动语义之前)。每当您有一个需要特殊创建/销毁的数据成员时,请确保在所有构造函数和析构函数中正确处理它:复制/移动构造/赋值和销毁。
  3. 请注意,目前,无法正确编写复制构造函数/赋值运算符,因为您不会存储数组的大小,因此您不知道副本的大小应该是多少

    例如,如果将数组大小存储在名为int的{​​{1}}成员中,则复制构造函数可能如下所示:

    i

    编写复制赋值运算符有点棘手,因为您需要处理MyClass(const MyClass& rhs) : a(0), i(rhs.i) { a = new int[i]; std::copy(rhs.a, rhs.a+rhs.i, a); } 现有数组,甚至在重新分配新数组时还原原始状态会引发异常:

    编辑:抱歉,我以前的delete示例是完全废话,此版本更好:

    operator=

    您只能在构建新成员之后替换现有成员。这样,如果分配新的抛出异常,则该对象仍处于旧状态。

答案 2 :(得分:0)

这是因为同样的&#34; a&#34;被删除了两次。 发生了什么:

  1. MyClass c(1)//分配了一个地址1
  2. MyClass(2)//分配了一个地址2
  3. c = ... //现在c.a指向地址2,因为c只复制右侧对象的每个成员
  4. 在2.处创建的对象被销毁,因此地址2被释放
  5. c被销毁,因此地址2第二次被释放,导致崩溃
  6. 解决方案不是复制&#34; a&#34;的地址,而是创建一个复制构造函数并复制&#34; a&#34;的值。代替。