2012-11-27 6 views
9

According to another answer, un riferimento rvalue non prolungare la vita di un temporaneo se l'espressione si riferisce ad esso è espressione xValue. Dal momento che std::move restituisce un riferimento rvalue, l'espressione di chiamare è un xValue e quindi i seguenti risultati in una un riferimento penzoloni:Estensione della durata di un temporaneo con un riferimento rvalue

int main() 
{ 
    std::string&& danger = std::move(get_string()); // dangling reference ! 
    return 0; 
} 

va bene. std::move non ha senso qui; è già un valore.

Ma ecco dove sto disegnando uno spazio vuoto. In che modo questo è diverso dal passare un'espressione xvalue come argomento, dall'uso completamente standard di std::move e dai riferimenti rvalue?

void foo(const std::string& val); 
// More efficient foo for temporaries: 
void foo(std::string&& val); 

int main() 
{ 
    std::string s; 
    foo(std::move(s)); // Give up s for efficiency 
    return 0; 
} 

C'è una regola speciale per gli argomenti di riferimento rvalue che estenderanno la durata di una temporanea indipendentemente dal fatto che si tratta di un prvalue o xValue? O è l'espressione di chiamata std::move solo un valore x perché abbiamo passato qualcosa che era già un valore? Io non la penso così perché restituisce comunque un riferimento di rvalue, che è un valore x. Sono confuso qui. Penso che mi manchi qualcosa di stupido.

+0

Non correlato: se la funzione 'pippo' sta per copiare o spostare in un modo o nell'altro, è sufficiente prendere l'argomento per valore e lasciare che il compilatore esegua la copia o lo spostamento. –

+0

Una nota sul tuo primo esempio: 'std :: move (get_string())' non è un'espressione temporanea. L'espressione temporanea era 'get_string()', ma poi la lanci. Quindi la regola su un'espressione temporanea vincolante per un riferimento non si applica più. –

risposta

7

Qui non è necessario prolungare la durata di vita: l'oggetto in questione dura fino alla fine di main, ovvero dopo la fine di foo.

+0

In effetti ... non ci sono nemmeno i provvisori nel codice indicato. – Mankarse

+4

Oh mio dio. Ho bisogno di dormire. –

8

Il secondo esempio non passa un riferimento a un riferimento temporaneo, sta passando un riferimento alla variabile s, che dura fino alla fine di main().

Se lo fosse (ad esempio foo(std::move(get_string()));), la durata del temporaneo dura fino alla fine dell'espressione completa, dopo che la funzione è tornata. È quindi abbastanza sicuro utilizzarlo entro foo. C'è solo un pericolo se foo memorizza un riferimento/puntatore al suo argomento, e qualcos'altro prova a usarlo in seguito.

+1

Ma è illegale prendere indirizzi di rvalue. – user1095108

+4

@ user1095108 ma 'val' non è un valore rvalore nel corpo della funzione' foo (std :: string && val) '. È un lvalue di tipo "riferimento di rvalore". Perfettamente legale per prendere il suo indirizzo, e usare il suo indirizzo, fino alla fine della vita di 's'. – Oktalist