oggetti eliminazione di tipo incompleto
-
29-09-2019 - |
Domanda
Questo mi ha fatto pensare:
class X;
void foo(X* p)
{
delete p;
}
Come possiamo delete p
se non abbiamo nemmeno sapere se X
ha distruttore visibile? g ++ 4.5.1 dà tre avvertimenti:
warning: possible problem detected in invocation of delete operator: warning: 'p' has incomplete type warning: forward declaration of 'struct X'
E poi si dice:
Nota: né il distruttore, né l'operatore specifica classe di eliminazione sarà chiamato, anche se sono dichiarati quando la classe è definita.
Wow ... sono compilatori necessari per diagnosticare questa situazione come g ++ fa? O è un comportamento indefinito?
Soluzione
Dalla serie [expr.delete]:
Se l'essere oggetto eliminato ha tipo di classe incompleta al punto di la cancellazione e la classe completa ha un non banale distruttore o un funzione deallocazione, il comportamento è non definito.
Quindi, è UB se c'è roba banale da fare, ed è ok se non c'è. Avvertenze non sono neccessary per UB.
Altri suggerimenti
Si tratta di un comportamento indefinito.
Tuttavia, è possibile effettuare il check-compilatore per i tipi incompleti, come spinta:
// verify that types are complete for increased safety
template<class T> inline void checked_delete(T * x)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}
L'applicazione di sizeof
a un tipo incompleto dovrebbe far scattare un errore, e suppongo che passa se con qualche compilatore, quindi un array di dimensione negativa farebbe scattare un errore.
È comportamento indefinito, e un Gotcha comune quando attuazione del modello Pimpl. Al meglio della mia conoscenza, semplicemente non c'è cosa come un avvertimento che il compilatore è tenuto ad emettere. Avvertimenti sono elettive; Sono lì perché lo scrittore compilatore pensato che sarebbe utile.