Domanda

Poche ore fa ero a giocherellare con un problema di perdita di memoria e si è scoperto che ho davvero avuto alcune cose di base circa i distruttori sbagliato virtuale! Mi permetta di mettere spiegare il mio design di classe.

class Base
{
  virtual push_elements()
  {}
};

class Derived:public Base
{
vector<int> x;
public:
   void push_elements(){ 
      for(int i=0;i <5;i++)
         x.push_back(i); 
   }
};

void main()
{
    Base* b = new Derived();
    b->push_elements();
    delete b;
}

Lo strumento limiti correttore riportato una perdita di memoria nel vettore classe derivata. E ho capito che il distruttore non è virtuale e il distruttore classe derivata non viene chiamato. Ed è sorprendentemente ottenuto risolto quando ho fatto il distruttore virtuale. Non è il vettore deallocata automaticamente anche se il distruttore della classe derivata non si chiama? È una stranezza nel strumento BoundsChecker o è la mia comprensione di sbagliato distruttore virtuale?

È stato utile?

Soluzione

Eliminazione di un oggetto della classe derivata attraverso un puntatore classe base quando la classe base non ha un virtuale porta distruttore comportamento indefinito.

Cosa hai potuto notare (che la parte della classe derivata dell'oggetto non viene distrutta e, pertanto, i suoi membri non si ottiene deallocato) è probabilmente il più comune di molti comportamenti possibili, e un buon esempio del perché è importante assicurarsi i tuoi distruttori sono virtuali quando si utilizza il polimorfismo in questo modo.

Altri suggerimenti

Se la classe di base non dispone di un distruttore virtuale, allora il risultato del codice è un comportamento indefinito, non necessariamente il distruttore sbagliato chiamato. Questo è probabilmente ciò che è BoundsChecker diagnosticare.

Anche se questo è tecnicamente definito, è comunque necessario conoscere il metodo più comune di fallimento al fine di diagnosticare esso. Questo metodo comune di fallimento è quello di chiamare il distruttore sbagliata. Non so di qualsiasi implementazione che non riuscirà in qualunque altro modo, anche se certamente io uso solo due implementazioni.

Il motivo per cui questo accade è la stessa ragione per la funzione di 'sbagliato' verrà chiamato quando si tenta di eseguire l'override una funzione di membro non virtuale e chiamare tramite un puntatore di base.

Se il distruttore non è virtuale, quindi il distruttore Base sarà chiamato. Il distruttore di base pulisce l'oggetto e finiture di base. Non c'è modo per il distruttore oggetto base da sapere sul oggetto derivato, deve essere il distruttore derivato chiamato e il modo per farlo, come con qualsiasi funzione, è quella di rendere il distruttore virtuale.

Dalla C ++ FAQ Lite: "Quando il mio dovrebbe essere distruttore virtuale?" Leggetelo qui . (C ++ FAQ Lite è una fonte eccellente per tutte le vostre domande relative al C ++, tra l'altro).

In C ++, un distruttore banale è un concetto ricorsivamente definito - è un distruttore che il compilatore ha scritto per voi quando ogni membro della classe (e ogni classe di base) ha un distruttore banale. (C'è un concetto simile chiamato il costruttore banale.)

Quando un oggetto con un distruttore non banale è incluso in un oggetto (come il vector nel tuo esempio), allora il distruttore dell'oggetto esterno (come il tuo Derived) in non è banale. Anche se non l'hai fatto distruttore di scrittura, il compilatore C ++ ha scritto automaticamente un distruttore che chiama i distruttori di tutti i membri che hanno distruttori.

Quindi, anche se non hai fatto nulla di scrittura, gli avvertimenti di scrivere un distruttore non virtuale si applicano ancora.

se si proviene da C #, allora hai fatto bene a chiedersi perché vettore non viene automaticamente de-allocata. Ma in C ++, gestione automatica della memoria non è availble a meno che non si utilizza il Microsoft Manged Extesions a C ++ (C ++ / CLI).

dal momento che non v'è alcun destructor in classe base è virtuale, l'oggetto della classe derivata non sarà mai liberato e là da voi perdita di memoria allocata per il membro di dati vettore della classe derivata.

Destructor è la funzione membro della classe il cui nome è lo stesso nome del nome della classe ed è preceduto dal segno tilde (~). Distruttore viene utilizzato per distruggere l'oggetto della classe quando l'oggetto esce dallo scope o si può dire che tutti su pulito di distruzione di classe devono essere fatto in distruttore. Tutta la memoria viene allocata durante la costruzione dell'oggetto nella classe viene distrutto (o rilascio memoria) quando l'oggetto passa nell'ambito.

Trova altri dettagli con esempio su BoundsCheck

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top