Ottimizzare C++/Ottimizzazione del codice C++/Numero di istruzioni: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
m Bot: Sostituzione automatica (-[[Categoria:Ottimizzare C++|Ottimizzare C++/ +[[Categoria:Ottimizzare C++|) |
Nessun oggetto della modifica |
||
Riga 2:
Anche i costrutti che generano del codice espanso ''inline'' possono avere un costo significativo, in quanto tali istruzioni devono pur essere eseguite.
=== Verifica di intervallo ===
Riga 18:
<source lang=cpp>unsigned(i) < unsigned(size)</source>
=== Ordine dei casi di istruzioni <code>switch</code> ===
Riga 24:
'''Nelle istruzioni <code>switch</code>, poni i casi in ordine di probabilità decrescente.'''
Nella linea-guida "Ordine dei casi dell'istruzione <code>switch</code>" del capitolo 3.1
Come ulteriore ottimizzazione, si dovrebbe contare, in esecuzioni tipiche, il numero di volte in cui viene eseguito ognuno dei singoli casi, e porre i casi in ordine da quello eseguito più volte a quello eseguito meno volte.
Riga 31:
'''Se un certo valore intero è una costante nel codice applicativo, ma è una variabile nel codice di libreria, rendilo un parametro di template.'''
Supponi che stai scrivendo la seguente funzione di libreria, in cui sia <code>x</code> che <code>y</code> non hanno un valore definito in fase di sviluppo della libreria:
<source lang=cpp>int f1(int x, int y) { return x * y; }</source>
Tale funzione può essere chiamata dal seguente codice applicativo, nel quale <code>x</code> non ha un valore costante, ma <code>y</code> è la costante 4:
<source lang=cpp>int a = f1(b, 4);</source>
Se mentre scrivi la libreria sai che il chiamante ti passerà sicuramente una costante intera come argomento <code>y</code>, puoi trasformare la funzione nel seguente template di funzione:
<source lang=cpp>template <int Y> int f2(int x) { return x * Y; }</source>
Riga 51:
<source lang=cpp>int f2(int x) { return x * 4; }</source>
* Viene passato un solo parametro alla funzione (
* La divisione per una costante intera (
* Dato che il valore costante (
In generale, i parametri di template interi sono delle costanti per chi istanzia il template e quindi per il compilatore, e le costanti sono gestite in modo più efficiente delle variabili.
Riga 63:
=== Il ''Curiously Recurring Template Pattern'' ===
'''Se devi scrivere una classe base astratta di libreria tale che in ogni algoritmo nel codice applicativo si userà una sola classe derivata da tale classe base, usa il [[w:en:Curiously recurring template pattern|''Curiously Recurring Template Pattern'']].'''
Supponi che stai scrivendo la seguente classe base di libreria:
Riga 75:
</source>
In questa classe, la funzione <code>g</code> esegue un algoritmo che usa una chiamata a <code>f</code> come punto di personalizzazione dell'algoritmo.
Lo scopo di questa classe è consentire di scrivere il seguente codice applicativo: <source lang=cpp>
Line 109 ⟶ 110:
</source>
In tal modo, si ha binding statico della funzione membro <code>Derivata1::f</code> alla funzione membro <code>Base<Derivata1>::g</code>, cioè la chiamata a tale funzione non è di tipo <code>virtual</code>, e può essere espansa ''inline''.
Tuttavia, con questa soluzione, se si volesse aggiungere la seguente definizione:
<source lang=cpp>
class
public:
void f() { ... }
Line 120 ⟶ 121:
</source>
non risulterebbe possibile definire un puntatore o riferimento a una classe base comune a <code>Derivata1</code> e <code>Derivata2</code>, in quanto tali classi risultano due tipi senza alcuna relazione;
Altre limitazioni sono le seguenti:
* <code>Base</code> è necessariamente un tipo astratto;
* un oggetto di tipo </code>Derivata1</code> non può essere convertito in un oggetto di tipo <code>Derivata2</code> o viceversa;
* per ogni derivazione di <code>Base</code>, tutto il codice macchina di <code>Base</code> viene duplicato.
=== Il pattern ''Strategy'' ===
'''Se un oggetto che implementa il pattern [[w:Strategy pattern|''Strategy'']] (noto anche come pattern ''Policy'') è una costante in ogni algoritmo nel codice applicativo, ma il codice di libreria deve poter gestire più strategie, elimina tale oggetto, rendi <code>static</code> tutti i suoi membri, e aggiungi tale classe come parametro di template.'''
Supponi che stai scrivendo il seguente codice di libreria, che implementa il design pattern ''Strategy'':
Line 159 ⟶ 160:
};
...
MyStrategy s; // Oggetto che rappresenta la mia strategia.
C c; // Oggetto contenente un algoritmo con strategia personalizzabile.
c.set_strategy(s); // Assegnazione della strategia.
c.f(); // Esecuzione dell'algoritmo con strategia assegnata.
</source>
Line 171 ⟶ 172:
class C {
public:
void f() {
if (Strategy::is_valid(*this)) Strategy::run(*this); }
};
</source>
Line 195 ⟶ 198:
=== Operatori bit-a-bit ===
'''Dovendo eseguire operazioni booleane su un insieme di singoli bit, affianca tali bit in
Gli operatori bit-a-bit (
[[Categoria:Ottimizzare C++|Ottimizzazione del codice C++/Numero di istruzioni]]
{{Avanzamento|
|