假设我有一个继承自A的A类和B类。 然后我做了类似的事情:
A* a = new B();
delete a;
为什么只有在B内有动态内存分配时才会发生内存泄漏? C ++如何知道删除" B部分"什么时候在B内有动态内存分配但是在哪里失败?
[更新:]
以下代码如何不会导致内存泄漏:[我怀疑它是未定义的行为,但我真的不明白:(]
#include <iostream>
using std::cout;
using std::endl;
class A {
public:
virtual void f() {
cout << "1" << endl;
}
~A() {
cout<< "A A'tor" << endl;
}
};
class B : public A {
private:
public:
B(){}
~B(){
cout<< "B D'tor" << endl;
}
void f() {
cout << "2" << endl;
}
};
int main() {
A* a = new B();
//a->f();
delete a;
return 0;
}
答案 0 :(得分:1)
编译器看到语句“删除a;” 它知道只有静态类型的“a”是指向A的指针,如果A类中没有虚拟析构函数。结果错误的析构函数被调用导致内存泄漏
如果A类中存在虚拟析构函数 然后编译器知道动态类型“a”是指向B的指针,并且会有一个vtable,它将在运行时获取B的析构函数地址
答案 1 :(得分:0)
这是因为析构函数不是虚拟的。如果程序中有可能通过基类指针删除派生类对象,则应在基类中定义虚拟析构函数。这将允许B的析构函数首先被调用,允许您释放B可能已分配的任何动态内存。 A的析构函数将在B之后被调用。
另一个好的经验法则是训练自己考虑让你的析构函数虚拟随时使你的方法变得虚拟。由于将方法设为虚拟的动机意味着您将在基类指针上调用方法,因此您可能会通过基类指针删除对象。