delete base class pointer without virtual destructor 会不会导致内存泄露?
Would it lead to memory leak when delete base class pointer without virtual destructor?
这里有一个例子来解释虚析构函数。(参见http://www.geeksforgeeks.org/g-fact-37/)
我根据那个例子修改了代码,对内存泄漏有疑问
假设Base class 有一个int num 变量,Derived class 有一个float money 变量。
调用delete base_ptr;
时,由于基class的析构函数是虚函数,所以应先调用~derived()
,再调用~Base()
。
我的问题是“函数 delete 是否足够聪明,以至于它可以释放为 int num(Base Class) 和 float money(Derived Class) 分配的内存?
我认为 base_ptr 是 Base* 类型的指针,因此它可能只释放 Base class 所需的内存量。然而,似乎 int 和 float 都将被释放,即使 base_ptr 是 Base class 的指向类型。如果是这样,我们把~Base()
设为非虚析构函数会不会导致内存泄漏?使用 ~Base()
的非虚拟析构函数,我们将错过 ~Derived()
的调用。因为 Base Class 和 Derived Class 都没有动态分配 "within",所以 ~Derived()
似乎根本没有释放任何内存,delete
的功能将释放 int num
和 float money
的内存。
#include <iostream>
using namespace std;
class Base {
public:
int num;
Base(int n):num(n){
cout<<"Base::Constructor\n";
}
virtual ~Base(){
cout<<"Base::Destructor\n";
}
};
class Derived : public Base {
private:
float money;
public:
Derived(int n, float m):Base(n),money(m){
cout<<"Derived::Constructor\n";
}
~Derived(){
cout<<"Derived::destructor\n";
}
};
int main() {
Base *base_ptr = new Derived(1,200.0);
delete base_ptr;
return 0;
}
您所描述的是未定义行为,这意味着任何讨厌的东西都可能出错,而不仅仅是内存泄漏。
但实际上,如果继承不是虚拟的,则派生的 class 没有其他基础 class,并且派生的 class 没有具有非平凡析构函数的成员,您可能会调用 Base::~Base()
析构函数,然后在指针上调用 operator delete
。 operator delete(void*)
函数只接受一个指针并释放它指向的所有内存,所以那里没有 "memory leak"。
这里有一个例子来解释虚析构函数。(参见http://www.geeksforgeeks.org/g-fact-37/) 我根据那个例子修改了代码,对内存泄漏有疑问
假设Base class 有一个int num 变量,Derived class 有一个float money 变量。
调用delete base_ptr;
时,由于基class的析构函数是虚函数,所以应先调用~derived()
,再调用~Base()
。
我的问题是“函数 delete 是否足够聪明,以至于它可以释放为 int num(Base Class) 和 float money(Derived Class) 分配的内存?
我认为 base_ptr 是 Base* 类型的指针,因此它可能只释放 Base class 所需的内存量。然而,似乎 int 和 float 都将被释放,即使 base_ptr 是 Base class 的指向类型。如果是这样,我们把~Base()
设为非虚析构函数会不会导致内存泄漏?使用 ~Base()
的非虚拟析构函数,我们将错过 ~Derived()
的调用。因为 Base Class 和 Derived Class 都没有动态分配 "within",所以 ~Derived()
似乎根本没有释放任何内存,delete
的功能将释放 int num
和 float money
的内存。
#include <iostream>
using namespace std;
class Base {
public:
int num;
Base(int n):num(n){
cout<<"Base::Constructor\n";
}
virtual ~Base(){
cout<<"Base::Destructor\n";
}
};
class Derived : public Base {
private:
float money;
public:
Derived(int n, float m):Base(n),money(m){
cout<<"Derived::Constructor\n";
}
~Derived(){
cout<<"Derived::destructor\n";
}
};
int main() {
Base *base_ptr = new Derived(1,200.0);
delete base_ptr;
return 0;
}
您所描述的是未定义行为,这意味着任何讨厌的东西都可能出错,而不仅仅是内存泄漏。
但实际上,如果继承不是虚拟的,则派生的 class 没有其他基础 class,并且派生的 class 没有具有非平凡析构函数的成员,您可能会调用 Base::~Base()
析构函数,然后在指针上调用 operator delete
。 operator delete(void*)
函数只接受一个指针并释放它指向的所有内存,所以那里没有 "memory leak"。