我这里有一段代码,其中我不明白为什么它会导致第22行(delete []语句)出现分段错误。你能解释一下吗?
#include<iostream>
#include<memory>
class A {
size_t a[1000];
public:
virtual ~A() { }
};
class B : public A {
public:
float b;
virtual ~B() { }
};
int main(int argc, char** argv){
A *b;
b = new B[10];
delete[] b;
return 0;
}
奇怪的是,如果B类没有任何成员变量(即我注释掉了行&#34;浮动b;&#34;)那么代码运行正常。
我的错误是什么?
答案 0 :(得分:11)
简单地说,你有未定义的行为。您无法向delete[]
提供您从new[]
获得的指针。您可能认为这样做,但是对于数组版本中的指针,它们的静态类型必须匹配。您将指针转换为指向基类的指针。
实际上,如果您没有添加float
,那么您的实施可能会保留sizeof(B) == sizeof(A)
。所以析构函数和释放函数调用不会立即做任何有害的事情。但它同样未定义。
答案 1 :(得分:3)
delete[] b;
将尝试删除A对象的数组,而不是B对象的数组。如果类B
没有任何成员变量,那么这些数组的大小恰好相同,这可能会让你躲避子弹。
当调用delete
时,它将访问存储在数组中的每个项目的vtable以调用虚拟析构函数。它将假设每个项目的大小为sizeof(A)
,因此如果sizeof(B)
不同,则访问第二项的vtable将在错误的偏移处执行。
答案 2 :(得分:1)
如果你想要一个数组的多态性,那么你需要创建一个指向基类的指针数组。