Come posso essere sicuro che una routine stia approfittando di (n) rvo?
-
09-12-2019 - |
Domanda
Mi piacerebbe assicurarmi che le mie routine stiano sfruttando (n) rvo quando possibile.Oltre ad analizzare attraverso lo smontaggio risultante, c'è qualcosa che posso fare o controllare se una routine viene compilata con (n) rvo?A questo punto sono per lo più interessato a MSVC e GCC.
Soluzione
No, non proprio.
Tuttavia è possibile seguire le linee guida quando scrivi il tuo codice.
.
Ottimizzazione del valore di ritorno senza nome
Questo è praticamente attivato ogni volta che si restituisce un temporaneo, anche in modalità Debug.
.
return MyObject(....);
.
denominato valore di ritorno ottimizzazione
Questo è praticamente attivato ogni volta che la funzione restituisce sempre lo stesso oggetto temporaneo:
.
MyObject func() {
MyObject result;
if (...) { return result; }
result.push(0);
return result;
}
Puoi mescolare quelli, ma diventa quasi impossibile per il compilatore applicare RVO in questo caso:
.
MyObject func() {
MyObject result;
if (...) { return MyObject(...); }
return result;
}
Qui, è probabilmente che un ritorno beneficerà di RVO e l'altro non lo farà. E scommetto sul primo essere ottimizzato perché saresti bloccato se crei in modo speculatore result
nello slot di ritorno e improvvisamente è necessario prendere il ramo if
. Si noti che semplicemente riordinare le dichiarazioni funziona solo:
.
MyObject func() {
if (...) { return MyObject(...); }
MyObject result;
return result;
}
Quindi la regola del pollice per NRVO è che non dovrebbe esserci un'istruzione return
tra la Dichiarazione di result
e l'istruzione return result;
che restituiscono qualsiasi altra cosa che result
stesso.
.
Se segui questo, impirai le probabilità a tuo favore. E poi è solo una questione di revisione del codice
E fai anche il tuo codice più facile da leggere poiché non dichiari le variabili prima di sapere che ne hai davvero bisogno!
Altri suggerimenti
È possibile aggiungere metodi di debug al distruttore:
struct A
{
~A() { cout << "destructor called"; }
};
A foo()
{
A a;
return a;
}
.
Se si chiama il distruttore, probabilmente RVO non è stato applicato.
Possibili modi in cui posso pensare sono:
- .
-
Implementazione di un meccanismo di conteggio di riferimento all'interno della tua classe che tiene traccia del numero di istanze create attraverso la classe, qualcosa di praticamente simile a un
shared_ptr
, in questo modo è possibile rilevare copie extra della classe che viene creata e rimossa seCopia Elision non sta accadendo. -
È possibile inserire semplicemente le tracce di debug nel costruttore di copia e nel distruttore per la tua classe, se la copia Elision non sta accadendo vedresti un sacco di costruttore di copia successivo e tracce di debug dei distruttori.