Ottimizzare C++/Scrivere codice C++ efficiente/Costruzioni e distruzioni: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
m Bot: Sostituzione automatica (-[[Categoria:Ottimizzare C++|Ottimizzare C++/Scrivere codice C++ efficiente/ +[[Categoria:Ottimizzare C++|) |
Nessun oggetto della modifica |
||
Riga 1:
{{Ottimizzare C++}}
La costruzione e la distruzione di un oggetto
In questa sezione vengono proposte linee-guida per ridurre il numero di creazione di oggetti, e quindi della loro corrispondente distruzione.
Riga 9:
'''Dichiara le variabili il più tardi possibile.'''
Dichiarare una variabile il più tardi possibile
Essere nell'ambito più stretto possibile comporta che se tale ambito non viene mai eseguito, l'oggetto associato alla variabile non viene mai costruito né distrutto.
Essere il più avanti possibile
Inoltre, spesso all'inizio di una routine non si ha un valore appropriato per inizializzare l'oggetto associato alla variabile, e quindi si è costretti a inizializzarla con un valore di default, e poi assegnarle il valore appropriato.
Se invece la si dichiara quando si ha a disposizione il valore appropriato, la si può inizializzare con tale valore senza bisogno di fare un successivo assegnamento, come suggerito dalla linea-guida "Inizializzazioni" in questa sezione.
=== Inizializzazioni ===
Riga 20:
'''Usa inizializzazioni invece di assegnamenti. In particolare, nei costruttori usa le liste di inizializzazione.'''
In generale, chiamare il costruttore di default seguito da un assegnamento di un valore è meno efficiente o ugualmente efficiente che chiamare solo un costruttore con tale valore.
Quindi, invece di scrivere:
<source lang=cpp>
string s;
...
s = "abc"
</source>
scrivi:
<source lang=cpp>
string s("abc");
</source>
=== Operatori di incremento/decremento ===
Line 29 ⟶ 42:
Se l'oggetto incrementato è di un tipo fondamentale, non ci sono differenze tra le due forme, ma se si tratta di un tipo composito, l'operatore postfisso comporta la creazione di un inutile oggetto temporaneo, mentre l'operatore prefisso no.
Siccome ogni oggetto che è attualmente di un tipo fondamentale potrebbe diventare in futuro di una classe, è bene usare sempre
=== Operatori compositi di assegnamento ===
Line 37 ⟶ 50:
'''Usa gli operatori compositi di assegnamento (come in <code>a += b</code>) invece degli operatori semplici combinati con operatori di assegnamento (come in <code>a = a + b</code>).'''
Tipicamente un operatore semplice, come nell'espressione
Per esempio, nel seguente codice, gli operatori
<source lang=cpp>
Line 45 ⟶ 58:
</source>
Il seguente codice, equivalente al precedente, risulta più efficiente, in quanto l'operatore
<source lang=cpp>
Line 56 ⟶ 69:
=== Passaggio di argomenti alle funzioni ===
'''Quando devi passare un argomento <code>x</code> di tipo <code>T</code> a una funzione, usa il seguente criterio:
**
***
**
***
**
***
**
***
**
***
Il passaggio per riferimento è più efficiente del passaggio per puntatore in quanto facilita al compilatore
Per oggetti che possono essere contenuti in uno o due registri, il passaggio per valore è più efficiente o ugualmente efficiente del passaggio per riferimento, in quanto tali oggetti possono essere contenuti in registri e non hanno livelli di indirettezza, pertanto questo è il modo più efficiente di passare oggetti sicuramente piccoli, come i tipi fondamentali, gli iteratori e gli oggetti-funzione.
Per oggetti più grandi di due registri, il passaggio per riferimento è più efficiente del passaggio per valore, in quanto
Un oggetto composito veloce da copiare potrebbe essere efficientemente passato per valore, ma, a meno che si tratti di un iteratore o di un oggetto-funzione, per i quali si assume l’efficienza della copia, tale tecnica è rischiosa, in quanto l’oggetto potrebbe diventare in futuro più lento da copiare.
Per esempio, se un oggetto di classe <code>Point</code> contiene solo due <code>float</code>, potrebbe essere efficientemente passato per valore; ma se in futuro si aggiungesse un terzo <code>float</code>, o se i due <code>float</code> diventassero due <code>double</code>, potrebbe diventare più efficiente il passaggio per riferimento.
Infine, è bene usare lo specificatore <code>const</code> per tutti i dati che non verranno modificati, in quanto tale informazione consente al compilatore alcuni tipi di ottimizzazione.
=== Dichiarazione <code>explicit</code> ===
Line 82 ⟶ 97:
'''Dichiara <code>explicit</code> tutti i costruttori che possono ricevere un solo argomento, eccetto i costruttori di copia delle classi concrete.'''
I costruttori
L'esecuzione Rendendo obbligatoriamente esplicita tale conversione, il compilatore potrebbe scegliere un'altra funzione in overload, evitando così di chiamare il costruttore, oppure segnalare l'errore e costringere il programmatore a scegliere Per i costruttori di copia delle classi concrete si deve fare eccezione, per consentirne il passaggio per valore.
Per le classi astratte, anche i costruttori di copia possono essere dichiarati <code>explicit</code>, in quanto, per definizione, le classi astratte non si possono istanziare, e quindi gli oggetti di tale tipo non dovrebbero mai essere passati per valore. === Operatori di conversione ===
'''Non dichiarare operatori di conversione, se non per mantenere la compatibilità con una libreria obsoleta (in C++0x, dichiarali <code>explicit</code>).'''
Gli operatori di
Se tali conversioni sono necessarie, fornisci invece una funzione membro equivalente, che può essere chiamata solo esplicitamente.
L'unico utilizzo che rimane accettabile per gli operatori di conversione si ha quando si
In === Idioma ''Pimpl'' ===
'''
L'idioma ''Pimpl'' (che significa Puntatore a IMPLementazione) consiste nel memorizzare nell'oggetto solamente un puntatore alla struttura che contiene tutte le informazioni utili di tale oggetto.
Line 115 ⟶ 134:
[[Categoria:Ottimizzare C++|Costruzioni e distruzioni]]
{{Avanzamento|
|