Ottimizzare C++/Ottimizzazione del codice C++/Numero di istruzioni: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
mNessun oggetto della modifica
Gian BOT (discussione | contributi)
m Bot: sostituisce source con syntaxhighlight
 
Riga 18:
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:
 
<sourcesyntaxhighlight lang=cpp>
int f1(int x, int y) { return x * y; }
</syntaxhighlight>
</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:
 
<sourcesyntaxhighlight lang=cpp>
int a = f1(b, 4);
</syntaxhighlight>
</source>
 
Se, mentre scrivi la libreria, sai che il chiamante ti passerà sicuramente una costante intera come argomento <code>y</code>, puoi trasformare la tua funzione nel seguente template di funzione:
 
<sourcesyntaxhighlight lang=cpp>
template <int Y> int f2(int x) { return x * Y; }
</syntaxhighlight>
</source>
 
Tale funzione può essere chiamata dal seguente codice applicativo:
 
<sourcesyntaxhighlight lang=cpp>
int a = f2<4>(b);
</syntaxhighlight>
</source>
 
Tale chiamata istanzia automaticamente la seguente funzione:
 
<sourcesyntaxhighlight lang=cpp>
int f2(int x) { return x * 4; }
</syntaxhighlight>
</source>
 
Quest'ultima funzione è più veloce della precedente funzione <code>f1</code>, per i seguenti motivi:
Riga 62:
Supponi che stai scrivendo la seguente classe base di libreria:
 
<sourcesyntaxhighlight lang=cpp>
class Base {
public:
Riga 69:
virtual void f() = 0;
};
</syntaxhighlight>
</source>
 
In questa classe, la funzione <code>g</code> esegue un algoritmo che chiama la funzione <code>f</code> come operazione astratta per l'algoritmo.
Riga 75:
Lo scopo di questa classe è consentire di scrivere il seguente codice applicativo:
 
<sourcesyntaxhighlight lang=cpp>
class Derivata1: public Base {
private:
Riga 83:
Base* p1 = new Derivata1;
p1->g();
</syntaxhighlight>
</source>
 
In tal caso, è possibile convertire il precedente codice di libreria nel seguente:
 
<sourcesyntaxhighlight lang=cpp>
template <class Derivata> class Base {
public:
Riga 94:
void f() { static_cast<Derivata*>(this)->f(); }
};
</syntaxhighlight>
</source>
 
Il codice applicativo, di conseguenza, diventerà il seguente:
 
<sourcesyntaxhighlight lang=cpp>
class Derivata1: public Base<Derivata1> {
public:
Riga 106:
Derivata1* p1 = new Derivata1;
p1->g();
</syntaxhighlight>
</source>
 
In tal modo, si ha binding statico alla funzione membro <code>Derivata1::f</code> della chiamata a <code>f</code> fatta all'interno della funzione membro <code>Base<Derivata1>::g</code>, cioè la chiamata a tale funzione non è più di tipo <code>virtual</code>, e può essere espansa ''inline''.
Riga 112:
Tuttavia, supponiamo che si volesse aggiungere la seguente definizione:
 
<sourcesyntaxhighlight lang=cpp>
class Derivata2: public Base<Derivata2> {
public:
void f() { ... }
};
</syntaxhighlight>
</source>
 
Con questa soluzione non sarebbe più possibile definire un puntatore o riferimento a una classe base comune sia a <code>Derivata1</code> che a <code>Derivata2</code>, in quanto tali classi risultano due tipi senza alcuna relazione; di conseguenza, questa soluzione non è applicabile se si vuole permettere al codice applicativo di definire un contenitore di oggetti arbitrari derivati dalla classe Base.
Riga 132:
Supponi che stai scrivendo il seguente codice di libreria, che implementa il design pattern ''Strategy'':
 
<sourcesyntaxhighlight lang=cpp>
class C;
class Strategy {
Riga 147:
Strategy s_;
};
</syntaxhighlight>
</source>
 
Questo codice di libreria ha lo scopo di consentire il seguente codice applicativo:
 
<sourcesyntaxhighlight lang=cpp>
class MyStrategy: public Strategy {
public:
Riga 162:
c.set_strategy(s); // Assegnazione della strategia personalizzata.
c.f(); // Esecuzione dell'algoritmo con la strategia assegnata.
</syntaxhighlight>
</source>
 
In tal caso, è possibile convertire il precedente codice di libreria nel seguente:
 
<sourcesyntaxhighlight lang=cpp>
template <class Strategy>
class C {
Riga 174:
}
};
</syntaxhighlight>
</source>
 
Il codice applicativo, di conseguenza, diventerà il seguente:
 
<sourcesyntaxhighlight lang=cpp>
class MyStrategy {
public:
Riga 188:
C<MyStrategy> c; // Oggetto con strategia assegnata staticamente.
c.f(); // Esecuzione con strategia assegnata staticamente.
</syntaxhighlight>
</source>
 
In tal modo, si evita l'oggetto-strategia, e si ha il binding statico delle funzioni membro <code>MyStrategy::is_valid</code> e <code>MyStrategy::run</code>, cioè si evitano chiamate a funzioni <code>virtual</code>.