2015-04-24 18 views
11

In realtà sto pensando a oggetti banalmente distruttibili, non solo a POD (non sono sicuro che il POD possa avere una classe base).È sicuro cancellare un oggetto POD con un puntatore alla sua base?

Quando ho letto questa spiegazione per is_trivially_destructible da cppreference ho notato questo:

bagagli occupato da oggetti distruttibili banalmente può essere riutilizzato senza chiamare il distruttore.

Quindi, è sicuro di farlo:

struct A { 
    int a; 
}; 
struct B : A { 
    int b; 
}; 
int main() { 
    A* a = new B; 
    delete a; 
} 

B::~B() non si chiamerà - e per quanto ne so (si prega di correggere se sbaglio) l'intera memoria verrà liberata. E B::~B() di sicuro è banale.

So che questo codice di odori male, ma la mia domanda è solo circa sicurezza di questo codice ...

+0

Sei sicuro che 'a' punterà sempre a un'istanza' B' e che 'B' rimarrà banalmente distruttibile? Se qualcuno modifica "B" o lo sostituisce con una sottoclasse non banalmente distrutta di "B", introduce silenziosamente un bug. – Kos

+0

Non ho proprio capito il punto che stai cercando. Se si desidera riutilizzare un oggetto con allocazione dell'heap, non si libera la memoria dell'heap (associata alla chiamata di eliminazione) ma si manterrà l'istanza inutilizzata in una sorta di contenitore di riciclaggio anziché chiamare l'eliminazione su di esso. Probabilmente avresti anche un metodo "factory" per ottenere un'istanza, che prima tenterebbe di riciclare vecchie istanze prima di creare nuove istanze con nuove. – BitTickler

+0

Scratch il mio post precedente lol. Ha chiesto se ha bisogno di un distruttore virtuale senza mai usare quelle parole :) – BitTickler

risposta

18

No, questo non è consentito. [Expr.delete]/P3, sottolineatura mia:

Nella prima alternativa (oggetto di eliminazione), 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 eliminato e il tipo statico deve avere un distruttore virtuale o il comportamento non è definito.

In effetti, il comitato abbastanza recentemente rejecteda proposal to make deleting a POD via a pointer-to-base well-defined.

+2

Forse degno di nota è se la chiamata esplicita di ": operator delete (a)" sia una soluzione valida. Per quanto posso vedere, sarebbe valido. Non lo consiglierei, tuttavia, se esiste la possibilità che 'delete a;' in realtà abbia chiamato un diverso 'operator delete '. – hvd