Prenderò un'ipotesi selvaggia:
Il costruttore e il distruttore C ++ non sono affatto funzioni: sono macro. Vengono allineati all'ambito in cui viene creato l'oggetto e all'ambito in cui l'oggetto viene distrutto. A sua volta, non vi è alcun costruttore né distruttore, l'oggetto è solo IS.
In realtà, penso che le altre funzioni della classe non siano né funzioni, ma funzioni incorporate che NON vengono allineate perché ne prendi l'indirizzo (il compilatore si rende conto che ci sei sopra e non incorpora o incorpora il codice nella funzione e ottimizza quella funzione) e, a sua volta, la funzione sembra "essere ancora lì", anche se non lo sarebbe se non l'avessi presa in considerazione.
La tabella virtuale dell '"oggetto" C ++ non è come un oggetto JavaScript, dove è possibile ottenere il suo "costruttore" e crearne oggetti in fase di runtime tramite new XMLHttpRequest.constructor
, ma piuttosto una raccolta di puntatori a funzioni anonime che agiscono come mezzi per interfacciarsi con questo oggetto , esclusa la possibilità di creare l'oggetto. E non ha nemmeno senso "eliminare" l'oggetto, perché è come provare a eliminare una struttura, non puoi: è solo un'etichetta di pila, basta scriverci come ti pare sotto un'altra etichetta: sei libero di usa una classe come 4 numeri interi:
/* i imagine this string gets compiled into a struct, one of which's members happens to be a const char * which is initialized to exactly your string: no function calls are made during construction. */
std::string a = "hello, world";
int *myInt = (int *)(*((void **)&a));
myInt[0] = 3;
myInt[1] = 9;
myInt[2] = 20;
myInt[3] = 300;
Non c'è perdita di memoria, non ci sono problemi, tranne per il fatto che hai effettivamente sprecato un sacco di spazio dello stack riservato all'interfaccia degli oggetti e alla stringa, ma non distruggerà il tuo programma (finché non provi a usarlo come una stringa mai più).
In realtà, se le mie assunzioni precedenti sono corrette: il costo completo della stringa è solo il costo di memorizzazione di questi 32 byte e lo spazio della stringa costante: le funzioni vengono utilizzate solo al momento della compilazione e possono anche essere incorporate e eliminate dopo l'oggetto viene creato e utilizzato (come se si stesse lavorando con una struttura e si riferisse ad esso solo direttamente senza alcuna chiamata di funzione, sicuramente ci sono chiamate duplicate invece di salti di funzione, ma di solito è più veloce e utilizza meno spazio). In sostanza, ogni volta che chiamate una funzione, il compilatore sostituisce semplicemente quella chiamata con le istruzioni per farlo letteralmente, con l'eccezione che i progettisti del linguaggio hanno impostato.
Riepilogo: gli oggetti C ++ non hanno idea di cosa siano; tutti gli strumenti per interfacciarsi con essi sono integrati staticamente e persi in fase di esecuzione. Ciò rende il lavoro con le classi efficiente quanto il riempimento di strutture con i dati e il lavoro diretto con tali dati senza chiamare alcuna funzione (queste funzioni sono incorporate).
Questo è completamente diverso dagli approcci di COM / ObjectiveC e javascript, che mantengono dinamicamente le informazioni sul tipo, a scapito del sovraccarico di runtime, della gestione della memoria, delle chiamate di costruzioni, poiché il compilatore non può buttare via queste informazioni: è necessario per spedizione dinamica. Questo a sua volta ci dà la possibilità di "parlare" con il nostro programma in fase di esecuzione e svilupparlo mentre è in esecuzione con componenti riflettenti.