2011-10-02 17 views
11

C'è bisogno prestazioni -wise per linea funzioni di passare i suoi argomenti da const riferimento comein linea Argomenti funzione Passare

foo(const T & a, const T &b) 

rispetto al valore da

foo(T a, T b) 

se Non cambio i valori di aeb nella funzione? C++ 11 cambia suggerire qualcosa di specifico qui?

+2

Un valore è un valore e un riferimento è un riferimento.Passare un riferimento const quando il significato invece di passare un valore è un errore che può mordere male. Vedi http://stackoverflow.com/questions/4705593/int-vs-const-int/4705871#4705871 – 6502

+0

@ 6502: questo è un ottimo esempio di caso in cui l'utilizzo di un riferimento rende la logica più complicata ('v.push_back (v [0]) 'è legale, perché la libreria standard deve includere quella logica extra). –

+0

@ BenVoigt: bello vedere questa richiesta è stata aggiunta allo standard. Dove è dichiarato? – 6502

risposta

11

Il passaggio per valore può solo escludere la chiamata del costruttore di copia se l'argomento è temporaneo.

Il passaggio di tipi primitivi mediante riferimento const non avrà alcun costo quando la funzione è in linea. Tuttavia, il passaggio di un valore lvalue complesso impone una chiamata del costruttore di copie potenzialmente costosa. Quindi preferisci passare con riferimento const (se l'aliasing non è un problema).

+0

Oltre ai problemi di aliasing ci sono problemi di durata. – 6502

+0

@ 6502: sui valori restituiti, sicuramente. Per i parametri, possono verificarsi problemi a vita, ma sono molto rari. E li considererei comunque un sottoinsieme di problemi di aliasing. –

+0

@BenVoigt 'Il passaggio dei tipi primitivi tramite riferimento const non avrà alcun costo quando la funzione è in linea. Intendete" non avrà alcun vantaggio in termini di costi "? Puoi confermare se c'è qualcosa da guadagnare passando a 'const int &' o a' const int' quando la funzione è in linea? – Antonio

1

Il passaggio per riferimento è più rapido del valore in base al tipo di dati.
Tuttavia per le funzioni inline il corpo della funzione (e quindi tutti i riferimenti/passati in valori) vengono aggiunti alla riga di codice che sono utilizzati in ogni caso quindi tecnicamente non ci sono variabili in giro, solo più righe di codice nella stessa area .

riferimento http://www.cprogramming.com/tutorial/lesson13.html

C'è anche una risposta molto utile, secondo la domanda should-i-take-arguments-to-inline-functions-by-reference-or-value

  • Esempio potrebbe essere stato fuorviante, rimosso -
+1

Questo è interamente speculazione. – pmr

+1

Il passaggio per riferimento è più rapido del valore ** a seconda del tipo **. Anche il codice che utilizza un riferimento ha requisiti aggiuntivi (per gestire correttamente l'aliasing) e potrebbe richiedere un'ulteriore indiretta non necessaria per i tipi nativi passati per valore. – 6502

+0

Ci scusiamo, sono passato per puntatore a un valore misto per qualche strana ragione, sei corretto è solo più veloce per alcuni tipi di dati. Vi segnalo anche http://stackoverflow.com/questions/722257/should-i-take-arguments-to-inline-functions-by-reference-or-value che supporta il mio punto – Serdalis

4

Teoricamente quelli senza di riferimento potrebbero essere copiati in memoria in quanto vi è la possibilità che la funzione in linea possa modificarli (anche se in realtà non lo è).

In molti casi il compilatore è abbastanza intelligente da selezionare quel tipo di cose ma dipenderà dal compilatore e dalle impostazioni di ottimizzazione. Inoltre, se la funzione richiama qualsiasi funzione membro non const nelle variabili di classe, il compilatore dovrà essere abbastanza intelligente da controllare se sta modificando anche qualcosa.

Utilizzando un riferimento const si può sostanzialmente dare un'indicazione abbastanza chiara.

MODIFICA: Ho solo dato un'occhiata al codice macchina per un semplice test program compilato con GCC 4.6 in ddd. Il codice generato sembrava identico, quindi sembra essere ottimizzato. È comunque buona pratica per altri compilatori e se nient'altro fornisce una chiara indicazione sull'intento del codice. È anche possibile che ci siano situazioni più complesse che il compilatore non può ottimizzare.

Anche lo llvm online dissembler demo mostra il codice bit identico viene generato anche lì. Se disattivi l'ottimizzazione, è leggermente più lungo senza il riferimento const.
* 1964 byte - Nessun riferimento const (e nessun altro comando su funzioni/parametri)
* 1960 byte - Solo nessun riferimento const, ma altri consts.
* 1856 byte - Con riferimento a const e const.

+1

Se la funzione inline passa a e b a un'altra funzione, potrebbe non essere possibile ottimizzare la copia. Ad esempio, se la funzione inline chiama la funzione non in linea 'bar (a)' il compilatore deve copiare perché la barra potrebbe fare 'if (& a == & special) ...' e il chiamante originale potrebbe aver passato 'special'. –

+0

Riprovare, con un tipo non POD. –

+0

Non ha importanza per l'ottimizzatore se una funzione membro è dichiarata 'const' o no.Const-correctness è invisibile per l'ottimizzatore ed è qualcosa che è stato progettato solo per aiutare i programmatori (dando errori in fase di compilazione se si violano le dichiarazioni const), non l'ottimizzatore. – 6502