2011-08-26 4 views
7

Poco tempo fa, ho trovato un documento molto interessante su un aggiornamento delle prestazioni molto accurato per dynamic_cast in C++: http://www2.research.att.com/~bs/fast_dynamic_casting.pdf.Avanzamento rapido dinamico della fusione

Fondamentalmente, rende dynamic_cast in C++ molto più veloce della ricerca tradizionale nell'albero di ereditarietà. Come indicato nel documento, il metodo prevede un algoritmo di colaggio dinamico veloce e costante.

Questo documento è stato pubblicato nel 2005. Ora, mi chiedo se la tecnica sia mai stata implementata da qualche parte o se ci sono piani per implementarlo ovunque?

+1

Non so se alcuni compilatori lo usano, ma l'ho visto utilizzato in un paio di soluzioni RTTI basate su librerie. –

+0

Poiché la "allocazione" del "tipo ID" viene eseguita durante il tempo di collegamento (vedere la carta), come può raggiungere una biblioteca? Hai un esempio? –

+0

Non è esattamente la stessa cosa; gli ID sono assegnati tramite un altro metodo, ma usano comunque modulo per determinare un cast valido. –

risposta

7

Non so quali implementazioni vari compilatori utilizzano accanto a GCC (che non è lineare). Tuttavia, è importante sottolineare che il documento non propone necessariamente un metodo sempre più veloce delle implementazioni esistenti per tutti (o anche comuni) l'utilizzo. Propone una soluzione generale che è asintoticamente migliore man mano che le gerarchie di ereditarietà crescono.

Tuttavia, è raramente un buon progetto avere gerarchie di ereditarietà di grandi dimensioni, poiché tendono a forzare l'applicazione a diventare monolitica e inflessibile da modificare. I programmi con design flessibile tendono ad avere solo gerarchie per lo più con 2 livelli, una base astratta e un'implementazione di ruoli polimorfici di runtime per supportare il principio Open/Closed. In questi casi, camminare sul grafico dell'ereditarietà può essere semplice come un singolo puntatore di dereferenza e confronto, che può essere più veloce della somma-indice-poi-dereferenzialità-poi-confronto presentata da Gibbs e Stroustrup.

Inoltre, è importante sottolineare che è mai necessario scrivere un programma che utilizza dynamic_cast a meno che le proprie regole aziendali non lo richiedano. L'uso di dynamic_cast è sempre un'indicazione che il polimorfismo non viene utilizzato correttamente e il riutilizzo è compromesso. Se hai bisogno di un comportamento basato sul lancio di una gerarchia, l'aggiunta di un metodo virtuale fornisce la soluzione pulita. Se si dispone di una sezione di codice che esegue dynamic_cast-checks sui tipi, quella sezione di codice non verrà mai "chiusa" (nel significato del principio Open/Closed) e dovrà essere aggiornata per ogni nuovo tipo aggiunto al sistema. Una spedizione virtuale, d'altra parte, viene aggiunta solo su nuovi tipi, consentendo di rimanere aperti all'espansione e ancora chiudendo i comportamenti che operano sul tipo di base.

Quindi questo è davvero un suggerimento piuttosto accademico (che equivale a cambiare una mappa ad una hash_map algoritmicamente) che non dovrebbe avere effetti del mondo reale se viene seguito un buon design. Se le regole aziendali vietano il buon design (alcuni negozi potrebbero avere barriere di codice o problemi di proprietà del codice in cui non è possibile modificare le architetture esistenti nel modo in cui devono essere, né consentire la costruzione di adattatori come si farebbe comunemente per le librerie di terze parti), quindi è meglio non prendere la decisione su quale compilatore utilizzare in base a quale algoritmo è implementato. Come sempre, se le prestazioni sono fondamentali e devi utilizzare una funzione come dynamic_cast, profila il tuo codice. È possibile (e probabilmente in molti casi) che l'implementazione di tree-walking sia più veloce nella pratica.

Vedere anche the standards committee's review of implementations, including dynamic_cast e a well-known look at c++ in embedded environments and good use (which mentions Gibbs and Stroustrup in passing).

+0

Non sono un fan di tutto dynamic_cast, ma ci sono situazioni (di solito dovute all'utilizzo di terze parti o agli "hack" della lingua) dove è richiesto. Non è la prima volta che leggo che dynamic_cast è segno di un cattivo design e che lo stesso comportamento avrebbe potuto essere fatto altrimenti, ma mi piacerebbe molto avere una "prova" di questa affermazione o almeno alcuni suggerimenti ... –

+0

Il cast dinamico consente di accedere a un tipo convertibile ea un punto di diramazione per l'esecuzione condizionata. La prova standard mostra che un dispatch virtuale fornisce le stesse funzionalità, quindi qualsiasi chiamata "if (dynamic_cast <...> (...))" può essere convertita in dispatch virtuale semplicemente implementando il comportamento in una funzione virtuale. Una prova estesa di solito indica che le librerie di terze parti possono essere utilizzate in modo simile fornendo classi wrapper per la gerarchia, con il comportamento previsto. Questa trasformazione mostra che l'accesso all'implementazione non è richiesto. – ex0du5