我对自己经常问自己的一个问题表示怀疑,这就是情况:
两个类,没有虚拟析构函数
class Base { int myInt; }; class Derived : public Base { int myIntDerived; }; int main() { Base *base = new Derived; Derived *derived = new Derived; delete base; delete derived; }
说第一次删除会导致内存泄漏而第二次删除会不会是正确的?
说第一次删除会导致内存泄漏而第二次删除会不会是正确的?
第二个确实很好(虽然,你不想直接在实际程序中删除指针.一个应该使用智能指针),但你的第一个语句并不完全正确.
形式上,通过指向具有非虚拟析构函数的基础子对象的指针删除对象具有未定义的行为.内存泄漏是可能的,但不是必需的.实际上,在您的情况下,由于它们derived
或任何成员对象都没有分配任何将在析构函数中释放的动态内存,因此可能不会发生泄漏.
当程序具有未定义的行为时,内存是否泄漏是您最不关心的问题.
这是未定义的行为,实际上可能导致内存泄漏:
C++标准,[expr.delete],第3段[ ISO/IEC 14882-2014 ],声明:
在第一个备选(删除对象)中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为要删除的对象的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义.在第二个备选(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义.
由于既没有析构函数也Base
没有Derived
用户定义的析构函数,编译器会添加一个默认的析构函数.那些破坏者不是virtual
.
既然base
是a Base*
,则delete base
调用基类的析构函数,即Undefined Behavior.具体而言,当您使用资源时,它会导致内存泄漏; 在你的情况下,因为你的类只包含POD,我会说没有泄漏.
为了修复内存泄漏,应该为要继承的类定义一个虚拟析构函数:
struct Base { virtual ~Base() {} int myInt; }; struct Derived : Base { int myIntDerived; }; int main() { Base *base = new Derived; Derived *derived = new Derived; delete base; // OK delete derived; // OK }