2009-07-12 3 views

risposta

165
Beta_ab&& 
Beta::toAB() const { 
    return move(Beta_ab(1, 1)); 
} 

Questo restituisce un riferimento penzoloni, proprio come con il caso di riferimento lvalue. Dopo il ritorno della funzione, l'oggetto temporaneo verrà distrutto. Si dovrebbe tornare Beta_ab per valore, come la seguente

Beta_ab 
Beta::toAB() const { 
    return Beta_ab(1, 1); 
} 

Ora, è propriamente lo spostamento di un oggetto temporaneo Beta_ab nel valore di ritorno della funzione. Se il compilatore lo può, eviterà del tutto la traslazione, usando RVO (ottimizzazione del valore di ritorno). Ora, è possibile effettuare le seguenti operazioni

Beta_ab ab = others.toAB(); 

ed esso si sposterà costruire l'temporanea nella ab, o fare RVO omettere facendo una mossa o copiare tutto. Vi consiglio di leggere BoostCon09 Rvalue References 101 che spiega la questione, e di come (N) RVO capita di interagire con questo.


Il tuo caso di restituire un riferimento di rvalue sarebbe una buona idea in altre occasioni. Immagina di avere una funzione getAB() che invochi spesso su un temporaneo. Non è ottimale fare in modo che restituisca un riferimento di const-value per i provvisori rvalue. Si può implementare in questo modo

struct Beta { 
    Beta_ab ab; 
    Beta_ab const& getAB() const& { return ab; } 
    Beta_ab && getAB() && { return move(ab); } 
}; 

Nota che move in questo caso non è facoltativo, perché non è né un ab automatica locale né una rvalue temporanea. Ora, il ref-qualificazione&& dice che la seconda funzione viene richiamata sul provvisori rvalue, rendendo il seguente movimento, invece di copia

Beta_ab ab = Beta().getAB(); 
+32

avevo sempre assunto il problema di riferimento penzoloni è andato via automagically quando il tipo di ritorno è stato un riferimento al valore r. Sono contento di averlo chiarito prima che mi mordesse. Gli errori di stacking fanno schifo. –

+17

:) In realtà, i riferimenti rvalue sono "solo riferimenti" come i riferimenti lvalue. non copiano o archiviano nulla. –

+0

E anche se non elide i costruttori, il compilatore sa che può restituire un valore di riferimento per te automaticamente in modo sicuro. Ad esempio, secondo i miei esperimenti, 'return x;' è lo stesso di 'return std :: move (x)'. (dove 'x' è una variabile locale (ad esempio questo punto che ho fatto non si applica direttamente alla domanda originale sulla restituzione di un temporaneo)). –