Ottimizzare C++/Ottimizzazione del codice C++/Costruzioni e distruzioni: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
RamaccoloBot (discussione | contributi)
m Bot: Sostituzione automatica (-[[Categoria:Ottimizzare C++|Ottimizzare C++/Ottimizzazione del codice C++/ +[[Categoria:Ottimizzare C++|)
Nessun oggetto della modifica
Riga 8:
=== Valore di ritorno di funzioni ===
 
'''Per le funzioni che non siano espanse ''inline'', cerca di dichiarare il tipo di ritorno <code>void</code> o <code>bool</code> o intero o puntatore o riferimento. Comunque, evita di dichiarare un tipo di ritorno la cui copia sposta oltre 8 byte. Se non fosse fattibile, almeno costruisci l’oggettol'oggetto da ritornare nelle stesse istruzioni <code>return</code>.'''
 
Nella compilazione di una funzione non espansa ''inline'', il compilatore non può sapere se il valore di ritorno verrà usato, e quindi lo deve comunque generare.
Generare un intero o un puntatore o un riferimento costa poco o niente, ma generare numeri a virgola mobile od oggetti più complessi richiede tempo.
Se la copia comporta l'allocazione di risorse, il tempo richiesto è enormemente maggiore, ma anche senza allocazioni, il tempo richiesto cresce al crescere del numero delle word che vengono copiate quando si copia un oggetto di tale tipo.
 
Comunque, se si costruisce l'oggetto da ritornare nelle stesse istruzioni <code>return</code>, senza quindi assegnare tale valore a una variabile, si sfrutta l'ottimizzazione garantita dallo standard detta ''Return Value Optimization'', che previene la creazione di oggetti temporanei.
Alcuni compilatori riescono a evitare la creazione di oggetti temporanei anche se sono legati a variabili locali (''Named Return Value Optimization''), ma in generale questo non è garantito.
 
Alcuni compilatori riescono a evitare la creazione di oggetti temporanei, anche se questi sono legati a variabili locali (con la cosiddetta ''Named Return Value Optimization''), ma in generale questo non è garantito.
Per verificare se viene attuata una di tali ottimizzazioni, inserisci un contatore nei costruttori, nei distruttori, e negli operatori di assegnamento della classe dell'oggetto ritornato.
 
Per verificare se viene attuata una di tali ottimizzazioni, inserisciincrementa un contatore statico nei costruttori, nei distruttori, e negli operatori di assegnamento della classe dell'oggetto ritornato.
Nel caso non risultassero applicate ottimizzazioni, ricorri a una delle seguenti tecniche alternative:
* Rendi la funzione <code>void</code>, e aggiungile un argomento passato per riferimento, che funge da valore di ritorno.
* Trasforma la funzione in un costruttore del tipo ritornato, che riceve gli stessi parametri della funzione.
* Fai in modo che la funzione restituisca un oggetto di un tipo ausiliario che ruba le risorse e le cede all'oggetto destinazione, senza copiarle.
* Usa un ''expression template'', che è una tecnica avanzata, facente parte del paradigma di programmazione detto [[w:en:Template metaprogramming|Template metaprogramming]].
* Usa un ''rvalue reference'', introdotto dallo standard C++0x.
* Usa un ''expression template''.
 
=== Spostamento di variabili all'esterno di cicli ===
 
'''Se una variabile è dichiarata all’internoall'interno di un ciclo, e l'assegnamento ad essa costa di meno di una costruzione e una distruzione, sposta tale dichiarazione prima del ciclo.'''
 
Se la variabile è dichiarata all’internoall'interno del ciclo, l’oggettol'oggetto associato ad essa viene costruito e distrutto ada ogni iterazione, mentre se è esterna al ciclo, tale oggetto viene costruito e distrutto una volta sola, e viene invece assegnato nel corpo del ciclo.
 
Tuttavia, in molti casi un assegnamento costa esattamente quanto una coppia costruzione+distruzione, per cui in tali casi non ci sono vantaggi a spostare la dichiarazione all’esternoall'esterno e aggiungere un assegnamento all'interno.
 
=== Operatore di assegnamento ===
 
'''In un overload dell'operatore di assegnamento (operator=), se sei sicuro che non solleverà eccezioni, non usare la tecnica ''copy&swap'', che crea una copia temporanea dell’oggetto sorgente, ma copia i singoli membri.'''
 
La tecnica più efficiente per copiare un oggetto è imitare il costruttore di copia, cioè prima copiare gli oggetti base, e poi gli oggetti membro, in ordine di dichiarazione.
 
Tuttavia, tale tecnica non è ''exception-safe'', cioè corre il rischio di non chiamare il distruttore di qualche oggetto nel caso venga sollevata un'eccezione durante la copia.
La tecnica più efficiente per copiare un oggetto è imitare il costruttore di copia, cioè prima copiare gli oggetti base e poi gli oggetti membro, in ordine di dichiarazione.
Pertanto, se c'è la possibilità che durante la copia venga sollevata un'eccezione, si deve usare una tecnica ''exception-safe'', che tuttavia non avrà prestazioni ottimali.
La tecnica di assegnamento ''exception-safe'' più elegante è quella detta ''copy&swap'', esemplificata dal seguente codice in cui <code>C</code> rappresenta il nome della classe:
 
Tuttavia, tale tecnica non è ''exception-safe'', cioè corre il rischio di non chiamare il distruttore di qualche oggetto nel caso venga sollevata un’eccezione durante la copia. Pertanto, se c’è la possibilità che durante la copia venga sollevata un’eccezione, si deve usare una tecnica ''exception-safe'', che tuttavia non avrà prestazioni ottimali. La tecnica di assegnamento “exception-safe” più elegante è quella detta ''copy&swap'', esemplificata dal seguente codice:
<source lang=cpp>
C& C::operator=(C new_value) {
Line 58 ⟶ 62:
 
[[Categoria:Ottimizzare C++|Costruzioni e distruzioni]]
{{Avanzamento|75100%|2326 maggio 2008}}