Appunti tratti dalla rilettura di More Effective C++ di Scott Meyers. Quarto blocco: Efficienza.
(24) Funzioni virtuali, ereditarietà multipla, classi base virtuali, RTTI hanno un costo.
Quando viene chiamata una funzione virtuale, il codice eseguito deve corrispondere al tipo dinamico dell'oggetto su cui la funzione é invocata. In genere questo meccanismo viene implementato per mezzo di una virtual table e di puntatori alla virtual table, solitamente citati come vtbl e vptr.
La vtbl é solitamente un array di puntatori a funzione.
Tra i costi delle funzioni virtuali c'é dunque quello relativo alla allocazione della vtbl, che ha dimensioni proporzionali al numero di funzioni virtuali presenti nella classe.
Una classe che ha funzioni virtuali deve avere poi un membro nascosto che gli permetta di accederla, il vptr. In pratica la nostra classe occuperà più spazio in memoria rispetto alla sua versione non-virtuale.
Il costo di chiamare una funzione virtuale, rispetto a una non-virtuale é solo leggermente più alto, dato che tutto il meccanismo della determinazione del codice da invocare é fatto via calcoli su puntatori. Il problema é che é praticamente impossibile usare l'ottimizzazione "inline" su una funzione virtuale, dato che é una ottimizzazione a compile-time, mentre la risoluzione della chiamata a una funzione virtuale avviene a runtime.
L'ereditarietà multipla confonde ancora di più le acque, complicando la gestione della vtbl e richiedendo un vptr per classe base nella classe considerata.
Inoltre la MI porta spesso alla necessità di dichiarare la classe base come virtuale, implicando altri costi.
RTTI ci permette di avere informazioni su ogni classe e oggetto a runtime, che sono memorizzate in un oggetto di tipo type_info, accedibile per mezzo dell'operatore typeid. In genere la RTTI viene implentata basandosi sulla vtbl.
Nessun commento:
Posta un commento