Fare riferimenti rvalue permettono penzoloni riferimenti?
Domanda
Si consideri il seguente.
#include <string>
using std::string;
string middle_name () {
return "Jaan";
}
int main ()
{
string&& danger = middle_name(); // ?!
return 0;
}
Questa non calcola nulla, ma si compila senza errori e dimostra una cosa che mi confonde:? danger
è un riferimento penzoloni, non è vero
Soluzione
Do riferimenti rvalue permettono penzoloni riferimenti?
Se si intende "E 'possibile creare penzoloni riferimenti rvalue", quindi la risposta è sì. Il vostro esempio, tuttavia,
string middle_name () {
return "Jaan";
}
int main()
{
string&& nodanger = middle_name(); // OK.
// The life-time of the temporary is extended
// to the life-time of the reference.
return 0;
}
è perfettamente bene. La stessa regola si applica qui che fa questo esempio (articolo di Herb Sutter) sicuro pure. Se si inizializza un riferimento con un puro rvalue , il tempo di vita dell'oggetto tempoary ottiene esteso alla vita in tempo di riferimento. È ancora possibile produrre penzoloni riferimenti, però. Ad esempio, questo non è più sicuro:
int main()
{
string&& danger = std::move(middle_name()); // dangling reference !
return 0;
}
A causa std::move
restituisce un string&&
(che è non puro rvalue ) la regola che si estende dagli anni temporanei tempo di vita non si applica. Qui, std::move
restituisce un cosiddetto xValue . Un xValue è solo un riferimento rvalue senza nome. Come tale potrebbe riferirsi a qualsiasi cosa ed è fondamentalmente impossibile indovinare ciò che un riferimento restituito si riferisce a senza guardare implementazione della funzione.
Altri suggerimenti
riferimenti rvalue si legano ai rvalues. Un rvalue è o un prvalue o un xValue [ spiegazione ]. Il legame con l'ex non crea mai un riferimento penzoloni, il legame con il secondo potrebbe. Ecco perché è generalmente una cattiva idea di scegliere T&&
come tipo di ritorno di una funzione. std::move
è un'eccezione a questa regola.
T& lvalue();
T prvalue();
T&& xvalue();
T&& does_not_compile = lvalue();
T&& well_behaved = prvalue();
T&& problematic = xvalue();
danger
è un riferimento penzoloni, non è vero?
Non più di quanto se si fosse usato un const &
:. danger
assume la proprietà del rvalue