2010-01-25 21 views
5

Come si utilizza l'ottimizzazione del valore di ritorno ?
C'è qualche caso in cui posso fidarmi di un compilatore moderno per utilizzare l'ottimizzazione, o dovrei sempre andare in modo sicuro e restituire un puntatore di qualche tipo/usare un riferimento come parametro?Fidati dell'ottimizzazione del valore restituito

Esistono casi noti in cui non è possibile effettuare l'ottimizzazione del valore di ritorno ?, Mi sembra che l'ottimizzazione del valore di ritorno sia abbastanza semplice da eseguire per un compilatore.

+2

Ricordare che il compilatore può decidere di non farlo, quando determina che il RVO non è in realtà un ottimizzazione nel caso specifico. Quindi, non solo devi fidarti del compilatore per farlo quando è utile, ma devi anche fidarti di esso _non_ farlo quando è inappropriato. – MSalters

+0

Per chiarire: un caso comune in cui è inappropriato è quando il tipo restituito può essere passato in un registro, ad es. una classe 'Radians'. La tecnica RVO utilizza lo spazio allocato nello stack e quindi ha il sovraccarico di accedere alla memoria. – MSalters

+0

@MSalters Ok, è interessante sapere. Fondamentalmente, l'ottimizzazione a cui sono interessato è di evitare ad esempio la copia di uno std :: vector <>. –

risposta

8

Ogni volta che le ottimizzazioni del compilatore sono abilitate (e nella maggior parte dei compilatori, anche quando le ottimizzazioni sono disabilitate), il RVO avrà luogo. NRVO è leggermente meno comune, ma la maggior parte dei compilatori eseguirà anche questa ottimizzazione, almeno quando le ottimizzazioni sono abilitate.

Hai ragione, l'ottimizzazione è abbastanza facile da eseguire per un compilatore, motivo per cui i compilatori lo fanno quasi sempre. Gli unici casi in cui "non può essere effettuato" sono quelli in cui l'ottimizzazione non si applica: RVO si applica solo quando si restituisce un temporaneo senza nome. Se si desidera restituire una variabile locale con nome, NRVO si applica invece, e mentre è un po 'più complesso da implementare per un compilatore, è fattibile, e i compilatori moderni non hanno problemi con esso.

+0

In particolare, se si hanno 2 variabili con nome e si riprende quello da restituire in fase di esecuzione, ovviamente il compilatore non può eseguire NRVO :) –

+0

Matthieu, suppongo che lo stesso vale per due uscite senza nome? (es. "if (...) return A() else return B();" –

+0

@Viktor: No - questo è RVO, non ** N ** RVO. Ne verrà costruito solo uno, quindi entrambi i percorsi di codice può usare la stessa memoria, che è la memoria riservata per il valore di ritorno.Questa è l'essenza di RVO: creare direttamente il valore di ritorno nella memoria a esso riservata – MSalters

2

Per avere le migliori possibilità che si verifica, è possibile restituire un oggetto costruito direttamente nella dichiarazione di ritorno [chiunque può ricordare il nome di questo linguaggio - ho dimenticato it]:

Foo f() { 
    .... 
    return Foo(...); 
} 

Ma come con tutte le ottimizzazioni, il compilatore può sempre scegliere di non farlo. E alla fine della giornata, se hai bisogno di restituire un valore, non c'è alternativa alla fiducia nel compilatore - puntatori e riferimenti non lo taglieranno.