L'oggetto foo
è una variabile locale con tipo Foo*
. Quella variabile probabilmente viene allocata nello stack per la funzione main
, proprio come qualsiasi altra variabile locale. Ma il valore memorizzato in foo
è un puntatore nullo. Non punta da nessuna parte. Non è presente alcuna istanza di tipo Foo
rappresentata da nessuna parte.
Per chiamare una funzione virtuale, il chiamante deve sapere a quale oggetto viene chiamata la funzione. Questo perché l'oggetto stesso è ciò che indica quale funzione dovrebbe essere effettivamente chiamata. (Questo è spesso implementato dando all'oggetto un puntatore a un vtable, una lista di puntatori di funzione, e il chiamante sa solo che dovrebbe chiamare la prima funzione dell'elenco, senza sapere in anticipo dove punta quel puntatore.)
Ma per chiamare una funzione non virtuale, il chiamante non ha bisogno di sapere tutto questo. Il compilatore sa esattamente quale funzione verrà chiamata, quindi può generare un'istruzione CALL
codice macchina per andare direttamente alla funzione desiderata. Passa semplicemente un puntatore all'oggetto in cui la funzione è stata richiamata come parametro nascosto per la funzione. In altre parole, il compilatore traduce tua chiamata di funzione in questo:
void Foo_say_hi(Foo* this);
Foo_say_hi(foo);
Ora, dal momento che l'attuazione di tale funzione non fa riferimento a tutti i membri dell'oggetto puntato da suo argomento this
, schivare efficacemente il proiettile di dereferenziamento di un puntatore nullo perché non ne viene mai denotato uno.
Formalmente, chiamare qualsiasi funzione - anche non virtuale - su un puntatore nullo è un comportamento non definito. Uno dei risultati consentiti di un comportamento indefinito è che il codice sembra funzionare esattamente come previsto. L'utente non dovrebbe fare affidamento su questo, anche se a volte si trovano librerie dal proprio fornitore del compilatore che do si basano su questo. Ma il fornitore del compilatore ha il vantaggio di poter aggiungere un'ulteriore definizione a quello che altrimenti sarebbe un comportamento indefinito. Non farlo da solo
fonte
2009-03-21 18:53:42
Vedere [this] (http://stackoverflow.com/questions/2474018/when-does-invoking-a-member-function-on-a-null-inull-instance-result-in-undefined-behav) per cosa la lingua dice a riguardo. Entrambi sono comportamenti indefiniti. – GManNickG