没有虚拟析构函数可能会发生内存泄漏?

时间:2012-01-06 00:58:05

标签: c++ polymorphism dynamic-memory-allocation virtual-destructor

#include <iostream>
using namespace std;
class base
{
   int a;
 public: 
   base() {a =0;}
 };
 class derv :public base
 {
   int b;
  public:
   derv() {b =1;}
 };
 int main()
 {
    base *pb = new derv();
    delete pb;
 }

我在derv类中没有虚拟析构函数,它是否只删除了derv对象的基本部分?

3 个答案:

答案 0 :(得分:21)

可能。

由于base没有虚拟析构函数,因此您的代码会显示未定义的行为。什么都可能发生。它可能看起来像你期望的那样工作。它可能泄漏内存。它可能会导致您的程序崩溃。它可能会格式化您的硬盘。

要求引用。 C ++11§5.3.5/ 3指出,对于标量delete表达式(即,不是delete[]表达式):

  

如果要删除的对象的静态类型与其动态类型不同,则静态类型应为要删除的对象的动态类型的基类,并且   静态类型应具有虚拟析构函数或行为未定义。

静态类型(base)与动态类型(derv)不同,静态类型没有虚拟析构函数,因此行为未定义。

答案 1 :(得分:0)

在源代码中没有内存泄漏,因为您没有动态创建的任何成员变量。

考虑案例1中的修改示例:

#include <iostream>
using namespace std;
class base
{
   int a;
 public: 
   base() {a =0;}
   ~base() 
     {
       cout<<"\nBase Destructor called";

     }
 };
 class derv :public base
 {
   int *b;

  public:
   derv() { b = new int;}
  ~derv()
  {
      cout<<"\nDerv Destructor called"; 
      delete b;
  }
 };
 int main()
 {
    base *pb = new derv();
    delete pb;
 }

在这种情况下,输出将是,

   Base Destructor called

在这种情况下会出现内存泄漏,因为'b'是使用'new'动态创建的,应使用'delete'关键字删除。由于未调用derv析构函数,因此不会删除它,因此存在内存泄漏。

考虑以下案例2:

#include <iostream>
using namespace std;
class base
{
   int a;
 public: 
   base() {a =0;}
   virtual ~base() 
     {
       cout<<"\nBase Destructor called";

     }
 };
 class derv :public base
 {
   int *b;

  public:
   derv() { b = new int;}
  ~derv()
  {
      cout<<"\nDerv Destructor called"; 
      delete b;
  }
 };
 int main()
 {
    base *pb = new derv();
    delete pb;
 }

在2输出的情况下,

Derv Destructor called 
Base Destructor called

在这种情况下没有内存泄漏。因为调用了derv析构函数而b被删除了。

析构函数可以在基类中定义为Virtual,以确保在删除指向派生类对象的基类指针时调用派生类析构函数。

我们可以说'当派生类动态创建成员时,析构函数必须是虚拟的'。

答案 2 :(得分:-1)

您的代码中没有内存泄漏。如果需要在派生类析构函数中释放一些内存,则会发生内存泄漏。