Ho una classe che accumula informazioni su un insieme di oggetti e può agire come un funtore o un iteratore di output. Questo mi permette di fare le cose come:Prevenzione di copie non necessarie di oggetti funtore C++
std::vector<Foo> v;
Foo const x = std::for_each(v.begin(), v.end(), Joiner<Foo>());
e
Foo const x = std::copy(v.begin(), v.end(), Joiner<Foo>());
Ora, in teoria, il compilatore dovrebbe essere in grado di utilizzare il copy elision and return-value optimizations in modo che solo un singolo oggetto Joiner
deve essere creato. In pratica, tuttavia, la funzione crea una copia su cui operare e quindi la copia nuovamente sul risultato, anche in build completamente ottimizzate.
Se creo il funtore come valore assegnabile, il compilatore crea due copie in più invece di uno:
Joiner<Foo> joiner;
Foo const x = std::copy(v.begin(), v.end(), joiner);
Se io goffamente forzare il tipo di modello a un riferimento che passa in un punto di riferimento, ma poi fa una copia di esso comunque e restituisce un riferimento penzoloni alla (ora distrutto) copia temporanea:
x = std::copy<Container::const_iterator, Joiner<Foo>&>(...));
posso fare le copie a basso costo utilizzando un riferimento allo stato, piuttosto che lo stato stesso nel funtore in stile di std::inserter
, che porta a qualcosa del genere ing come questo:
Foo output;
std::copy(v.begin(), v.end(), Joiner<Foo>(output));
Ma questo rende impossibile usare lo stile "funzionale" di oggetti immutabili, e in generale non è così bello.
C'è qualche modo per incoraggiare il compilatore ad eliminare le copie temporanee, o far passare un riferimento fino in fondo e restituire lo stesso riferimento?
L'utilità del RVO dipende probabilmente dalla definizione di "falegname". Detto questo, sei davvero disposto a rinunciare alla sintassi semplice e pulita 'Foo const x = std :: for_each (v.begin(), v.end(), Joiner());' qualcosa di molto più brutto? –
GManNickG
for_each/copy dovrebbe restituire un Joiner, non un Foo, giusto? Il tuo esempio mi confonde. A meno che tu non stia cercando di implicare Joiner è convertibile in Foo? –
Ho scritto tre diverse risposte per dimostrare che hai torto e alla fine hai capito che non lo sei. Molto utile, grazie per la domanda. +1. –