鉴于两个类只有原始数据类型而没有自定义析构函数/解除分配器。 C ++规范是否保证它将以正确的大小解除分配?
struct A { int foo; };
struct B: public A { int bar[100000]; };
A *a = (A*)new B;
delete a;
我想知道我是否需要写一个空的virtual
dtor?
我尝试过g ++和vc ++ 2008,它们不会导致泄漏。但我想知道C ++标准中的正确内容。
答案 0 :(得分:24)
除非基类析构函数是虚拟的,否则它是未定义的行为。见5.3.5 / 4:
如果[删除运算符]的操作数的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义
答案 1 :(得分:16)
根据C ++标准,你所拥有的是未定义的行为 - 这可能表现为泄漏,它可能不会,为了你的代码是正确的,你需要一个虚拟的析构函数。
此外,您不需要(A *)演员。每当你发现自己在C ++中使用C风格的强制转换时,你可以相当确定它是不必要的,或者你的代码是错误的。
答案 2 :(得分:1)
这是未定义的行为 - 也许一切都很好,也许出现了问题。要么不这样做,要么为基类提供虚拟析构函数。
在大多数实现中,这不会泄漏 - 类中没有堆分配的成员函数,因此完成delete
时唯一需要的是释放内存。解除分配内存只使用对象的地址,仅此而已,堆完成所有其余的工作。
答案 3 :(得分:1)
对于原始数据,我相信你很好。在这种情况下,您可能合法地不想承担v-table的费用。 否则,绝对是首选。
答案 4 :(得分:0)
它将以正确的大小释放,因为要释放的大小是您获得的堆内存区域的属性(没有传递给free()
的大小 - 就像函数一样!)。
然而,没有人被召唤。如果'B'定义了析构函数或包含任何具有非平凡析构函数的成员,则不会调用它们,从而导致潜在的内存泄漏。但是,在您的代码示例中并非如此。