6

这只是一个了解继承如何工作的测试项目。Cat 是 Mammal 的子类,而 Mammal 又是 Animal 的子类。

int main()
{
    Cat* cat1 = new Cat("nosy grey", 1.0d, 3);
    Cat* cat2 = new Cat("purply green", 2.0d, 4);

    Cat* cats[] = {cat1, cat2};

    delete [] cats;
 }

所以我真的不能那样做,因为那样我就明白了。

*** Error in `/home/max/git/info-2-ss/Blatt3/Aufgabe2/main.exe': double free or corruption (out): 0x00007fff55fd7b10 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x80a46)[0x7f3a07452a46]
/home/max/git/info-2-ss/Blatt3/Aufgabe2/main.exe[0x40178e]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0x7f3a073f3ea5]
/home/max/git/info-2-ss/Blatt3/Aufgabe2/main.exe[0x400d39]

当我的构造函数和析构函数被调用时,我会输出,所以当我的 Cats 被创建时,我会得到这样的结果:

Called ctor of Animal with age: 3
Called ctor of Mammal with hairLength: 1
Called ctor of Cat with eyecolor: nosy grey

当我稍微更改我的代码时,它显示为:

delete [] *cats;

那么我会期望每只猫都会像这样调用我的 dtors:

Called dtor of Cat
Called dtor of Mammal 
Called dtor of Animal 

相反,我得到了这一行:

Called dtor of Cat

摘要:如何有效地删除我的数组,以便调用我的所有 dtor?

4

4 回答 4

8

Cat* cats[] = {cat1, cat2};

使用自动存储创建一个指向猫的指针数组!你没有用 分配数组new[],所以你不应该用delete[].

于 2013-05-16T12:16:16.020 回答
2
for(i = 0; i < len(cats)/sizeof(Cat); i++) {
  delete cats[i];
}

delete[] cats仅当您cats使用cats = new Cat[num_cats].

于 2013-05-16T12:16:15.740 回答
2

delete[]仅当您从! new ...[]像这样:

Cat * cats = new Cat[2];
delete [] cats;

以上是正确的。但请注意,当然,在这种情况下,您不能将参数传递给构造函数。

现在,你的情况。您没有创建数组new,因此您不应该删除数组本身(它在堆栈上,而不是在堆中)。这就是delete[] cats崩溃的原因。接下来*cats将数组视为指针并解除对它的引用,即返回此指针指向的项目。对于数组,它是数组的开头:与 .*cats相同cats[0]。这就是为什么在您的第二次尝试中只删除第一项。

最后,答案是:代替所有这些,单独删除每个项目。对于您的简单案例:

delete cat1;
delete cat2;

或者,更一般地说:

for(int i = 0; i < sizeof(cats)/sizeof(cats[0]); ++i) {
    delete cats[i];
}

sizeof(cats)/sizeof(cats[0])是一个简单的技巧,通过将数组的大小除以元素的大小来获取数组中的项目数。

通过这种方式,您可以释放放置每个Cat对象的内存。如果您担心指针数组所在的内存- 它在堆栈上,这意味着它将在从函数返回时自动释放。

于 2013-05-16T12:23:26.900 回答
0

您不必删除数组本身,只需删除其元素。您的数组cats在堆栈上,因为您没有使用newor创建它malloc

所以你所要做的就是

delete cat1;
delete cat2;

或等效地

delete cats[0];
delete cats[1];
于 2013-05-16T12:16:18.623 回答