Risposte:
Beta_ab&&
Beta::toAB() const {
return move(Beta_ab(1, 1));
}
Ciò restituisce un riferimento pendente, proprio come nel caso del riferimento lvalue. Dopo che la funzione ritorna, l'oggetto temporaneo verrà distrutto. Dovresti restituire Beta_ab
per valore, come il seguente
Beta_ab
Beta::toAB() const {
return Beta_ab(1, 1);
}
Ora sta spostando correttamente un Beta_ab
oggetto temporaneo nel valore restituito della funzione. Se il compilatore può, eviterà del tutto lo spostamento, usando RVO (ottimizzazione del valore di ritorno). Ora puoi fare quanto segue
Beta_ab ab = others.toAB();
E si sposterà costruendo il temporaneo ab
, o facendo RVO per omettere di fare una mossa o copiare del tutto. Ti consiglio di leggere BoostCon09 Rvalue References 101 che spiega la questione e come (N) RVO capita di interagire con questo.
Il tuo caso di restituzione di un riferimento di valore sarebbe una buona idea in altre occasioni. Immagina di avere una getAB()
funzione che invochi spesso in modo temporaneo. Non è ottimale per farlo restituire un riferimento al valore costante per i temporali del valore. Puoi implementarlo in questo modo
struct Beta {
Beta_ab ab;
Beta_ab const& getAB() const& { return ab; }
Beta_ab && getAB() && { return move(ab); }
};
Si noti che move
in questo caso non è facoltativo, poiché ab
non è né un valore locale automatico né un valore temporaneo. Ora, il qualificatore ref &&
afferma che la seconda funzione è invocata sui provvisori rvalue, facendo la seguente mossa, invece di copiare
Beta_ab ab = Beta().getAB();
Si può essere più efficiente, ad esempio, in un contesto diverso bit:
template <typename T>
T&& min_(T&& a, T &&b) {
return std::move(a < b? a: b);
}
int main() {
const std::string s = min_(std::string("A"), std::string("B"));
fprintf(stderr, "min: %s\n", s.c_str());
return 0;
}
Come osservazione interessante, sulla mia macchina clang++ -O3
genera 54 istruzioni per il codice sopra rispetto a 62 istruzioni per il normale std::min
. Tuttavia, con -O0
esso genera 518 istruzioni per il codice sopra rispetto a 481 per il normale std::min
.
for(:)
e l'integrazione sull'oggetto deallocato. Correzione: ideone.com/tQVOal
std::move()
è solo usato come cast esplicito per illustrare il punto più chiaramente. Non è un codice che potresti copiare e incollare nel tuo progetto. Non contraddice la risposta più votata, perché all'interno della funzione viene creato un oggetto temporaneo. Qui l'oggetto restituito è uno degli argomenti (gli oggetti temporanei vengono distrutti come l'ultimo passo nella valutazione dell'espressione completa che (lessicamente) contiene il punto in cui sono stati creati).