11
#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; 
} 

Non ho un distruttore virtuale in classe derv, elimina solo la parte di base dell'oggetto derv ??Possibile perdita di memoria senza un distruttore virtuale?

+0

È la classe base che ha bisogno di un distruttore virtuale. – Yuushi

+0

@Mysticial: James ha questo. – Puppy

+0

@James, hai detto che anche la classe base non ha alcuna funzione virtuale ma deve avere un distruttore virtuale se vogliamo ereditare la classe base ?? – Alok

risposta

19

Potrebbe.

Poiché base non ha un distruttore virtuale, il codice mostra un comportamento non definito. Qualunque cosa potrebbe accadere. Potrebbe sembrare che funzioni come ci si aspetta. Potrebbe perdere memoria. Potrebbe causare il blocco del programma. Potrebbe formattare il tuo disco rigido.

È stata richiesta una citazione. C++ 11 §5.3.5/3 precisa che, per uno scalare delete espressione (cioè non un delete[] espressione):

se il tipo statico dell'oggetto da cancellare è diverso dal suo tipo dinamico, il tipo statico deve essere una classe base del tipo dinamico dell'oggetto da eliminare e il tipo statico deve avere un distruttore virtuale o il comportamento non è definito.

Il tipo statico (base) è diverso dal tipo dinamico (derv) e il tipo statico non ha un distruttore virtuale, quindi il comportamento è indefinito.

+2

La mancanza di distruttore virtuale in base indica che non verrà eseguita alcuna finalizzazione personalizzata specificata nel distruttore delle classi derivate. La memoria per oggetto sarebbe ancora deallocata correttamente. (Anche il distruttore di 'base' verrebbe chiamato se fosse definito da non-virtuale). – Xion

+6

@Xion: Davvero. Il comportamento non è definito. Tutte le scommesse sono disattivate. Nulla può essere detto con certezza sul comportamento del programma. –

+2

riferimento, per favore! – wilhelmtell

-1

Non c'è alcuna perdita di memoria nel codice. Ci sarebbe stata una perdita di memoria se fosse necessario liberare della memoria nel distruttore di classe derivato.

+6

Il comportamento non è definito. Tutte le scommesse sono disattivate. Nulla può essere detto con certezza sul comportamento del programma. –

-1

Nel codice sorgente non vi è perdita di memoria, poiché non si dispone di alcuna variabile membro creata dinamicamente.

consideri l'esempio modificato sotto Caso 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; 
} 

In questo caso l'uscita sarà,

Base Destructor called 

In questo caso v'è una perdita di memoria, poiché 'b' viene creata dinamicamente usando 'nuovo' che dovrebbe essere cancellato usando la parola chiave 'cancella'. Poiché derv destructor non viene chiamato non viene cancellato, quindi c'è perdita di memoria.

Si consideri il caso di sotto del 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; 
} 

Nel caso 2 uscita sarà,

Derv Destructor called 
Base Destructor called 

In questo caso non c'è memoria leak.because derv distruttore viene chiamato e B è sempre cancellato.

Il distruttore può essere definito come virtuale nella classe base per assicurarsi che il distruttore di classe derivato venga chiamato quando si elimina il puntatore della classe base che punta all'oggetto di classe derivato.

Possiamo dire che "Il distruttore deve essere virtuale quando la classe derivata ha creato dinamicamente membri".

+1

Il comportamento non è definito. Tutte le scommesse sono disattivate. Nulla può essere detto con certezza sul comportamento del programma. –

+1

@JamesMcNellis: nel codice precedente che ha l'allocazione di memoria nella classe derivata dovrebbe avere un distruttore virtuale. Altrimenti c'è una perdita di memoria. –