Возможна утечка памяти без виртуального деструктора? - PullRequest
11 голосов
/ 06 января 2012
#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 ]

21 голосов
/ 06 января 2012

Может.

Поскольку base не имеет виртуального деструктора, ваш код демонстрирует неопределенное поведение. Все может случиться. Может показаться, что работает как вы ожидаете. Это может привести к утечке памяти. Это может привести к сбою вашей программы. Это может отформатировать ваш жесткий диск.

Цитата была запрошена. C ++ 11 §5.3.5 / 3 гласит, что для скалярного delete выражения (т.е. не delete[] выражения):

если статический тип удаляемого объекта отличается от его динамического типа, статический тип должен быть базовым классом динамического типа удаляемого объекта и Статический тип должен иметь виртуальный деструктор или поведение не определено.

Статический тип (base) отличается от динамического типа (derv), и статический тип не имеет виртуального деструктора, поэтому поведение не определено.

0 голосов
/ 06 января 2012

В вашем исходном коде нет утечки памяти, поскольку у вас нет динамической переменной-члена, созданной.

Рассмотрим измененный пример, приведенный ниже. Случай 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».Поскольку деструктор дерв не вызывается, он не удаляется, поэтому имеется утечка памяти.

Рассмотрим приведенный ниже случай 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.

Деструктор может быть определен как виртуальный в базовом классе, чтобы обеспечить вызов деструктора производного класса примы удаляем указатель базового класса, который указывает на объект производного класса.

Мы можем сказать: «Разрушитель должен быть виртуальным, если производный класс имеет динамически создаваемые члены».

0 голосов
/ 06 января 2012

В вашем коде нет утечки памяти.Произошла бы утечка памяти, если бы вам нужно было освободить часть памяти в деструкторе производного класса.

...