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.

È stato utile?

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:

    .
  1. 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.

  2. È 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top