Ottimizzare C++/Scrivere codice C++ efficiente/Costrutti che peggiorano le prestazioni: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
Riportate modifiche da en.wikibooks |
|||
Riga 3:
Rispetto al linguaggio C, il linguaggio C++ aggiunge alcuni costrutti, il cui utilizzo peggiora l'efficienza.
Alcuni di
Altri costrutti sono invece alquanto inefficienti, e devono quindi essere usati con
In questa sezione si presentano le linee-guida per evitare i costi dei costrutti C++ che peggiorano le prestazioni.
Riga 11:
=== L'operatore <code>throw</code> ===
'''Chiama l'operatore <code>throw</code> solamente quando
Il sollevamento di una eccezione ha un costo molto elevato,
Se tale operazione viene effettuata solamente ogni volta che un messaggio viene mostrato all'utente o scritto in un file di log, si ha la garanzia che non verrà eseguita troppo spesso senza che ce ne si accorga.
=== Funzioni membro <code>static</code> ===
Riga 27:
=== Funzioni membro <code>virtual</code> ===
'''In ogni classe, definisci <code>virtual</code> il distruttore se e solo se la classe contiene almeno un'altra funzione membro <code>virtual</code>, e, a parte i costruttori e il distruttore, definisci <code>virtual</code> solamente le funzioni membro
Inoltre,
=== Derivazione <code>virtual</code> ===
'''Usa la derivazione <code>virtual</code> solo quando due o più classi devono condividere la rappresentazione di una classe base comune.'''
Per esempio, considera le seguenti definizioni di classe:
Line 47 ⟶ 45:
</source>
Con tali definizioni, ogni oggetto di classe C contiene due oggetti distinti di classe A, uno
Questo non costituisce un problema se la classe A non ha nessuna variabile membro non-<code>static</code>.
Se invece tale
<source lang=cpp>
Line 61 ⟶ 59:
Questa situazione è l'unica in cui è necessaria la derivazione <code>virtual</code>.
Se si usa la derivazione <code>virtual</code>, le funzioni membro della classe A sono un po' più lente da chiamare su un oggetto di classe C.
=== Template di classi polimorfiche ===
Riga 66:
'''Non definire template di classi polimorfiche.'''
In altre parole, non usare le parole-chiave "<code>template</code>" e "<code>virtual</code>" nella stessa definizione di classe.
I template di classe, ogni volta che vengono istanziati, producono una copia delle funzioni utilizzate della classe, e se tali classi contengono funzioni virtuali, vengono replicate anche le ''vtable'' e le informazioni ''RTTI''.▼
▲I template di classe, ogni volta che vengono istanziati, producono una copia
Questi dati ingrandiscono eccessivamente il programma.
=== Uso di deallocatori automatici ===
Line 87 ⟶ 77:
La garbage collection, cioè il recupero automatico della memoria non più referenziata, fornisce la comodità di non doversi occupare della deallocazione della memoria, e previene i [[w:Memory leak|''memory leak'']].
Tale funzionalità non viene fornita dalla libreria standard, ma viene fornita da librerie non-standard.
Tuttavia, tale tecnica di gestione della memoria
La libreria standard del C++98 contiene un solo smart-pointer, l'<code>auto_ptr</code>, che è efficiente. Altri smart-pointer sono forniti da librerie non-standard, come Boost, o verranno forniti dal C++0x.
Line 93 ⟶ 83:
In particolare, compilando con l'opzione di gestione del multithreading, tali puntatori hanno pessime prestazioni nella creazione, distruzione e copia dei puntatori, in quanto devono garantire la mutua esclusione delle operazioni.
Normalmente bisognerebbe, in fase di progettazione, cercare di assegnare ogni oggetto allocato dinamicamente ad un proprietario, cioè a un altro oggetto che lo possiede
Solo quando tale assegnazione risulta difficile, in quanto più oggetti tendono a rimpallarsi la responsabilità di distruggere l'oggetto, risulta opportuno usare uno smart-pointer con reference-count per gestire tale oggetto.
Line 100 ⟶ 90:
'''Definisci <code>volatile</code> solamente quelle variabili che vengono modificate in modo asincrono da dispositivi hardware o da più thread.'''
L'uso del modificatore <code>volatile</code> impedisce al compilatore di allocare una variabile in un registro, anche per un breve periodo.
Questo garantisce che tutti i dispositivi e tutti i thread ''vedano'' la stessa variabile, ma rende molto più lente le operazioni che manipolano tale variabile.
|