In primo luogo, alcuni consigli generali su come utilizzare auto
che non è specifico per forchetta. auto&&
può essere problematico se l'inizializzatore è un valore x riferito a un valore temporaneo, poiché in questo caso l'estensione della durata non può essere applicata. Per dirla più semplicemente, e con il codice:
// Pass-through identity function that doesn't construct objects
template<typename T>
T&&
id(T&& t)
{ return std::forward<T>(t); }
// Ok, lifetime extended
// T {} is a prvalue
auto&& i = T {};
T* address = &i;
// Still ok: lifetime of the object referred to by i exceed that of j
// id(whatever) is an xvalue
auto&& j = id(std::move(i));
// No other object is involved or were constructed,
// all those references are bound to the same object
assert(&j == address);
// Oops, temporary expires at semi-colon
// id(whatever) is an xvalue, again
auto&& k = id(T {});
La grande indizio che ci sia qualcosa di losco succedendo qui è che id
ha tipo T&&
tornare. Se restituisse T
allora id(whatever)
sarebbe un valore di prvalore e il temporaneo restituito avrebbe avuto la sua durata estesa (tuttavia ciò implicherebbe una costruzione).
Con quella di mezzo, quando si tratta di gamma-for anche se bisogna ricordare che for(auto&& ref: init) { /* body */ }
è specificato di essere più o meno equivalente al seguente (ignorando alcuni dettagli che non contano qui):
{
using std::begin;
using std::end;
auto&& range = init;
for(auto b = begin(range), e = end(range); b != e; ++b) {
auto&& ref = *b;
/* body */
}
}
Dobbiamo chiederci ora, che cosa se *b
è un xValue (cioè il tipo iteratore ha un operator*
ritorno value_type&&
, come è il caso ad esempio con std::move_iterator<Iterator>
)? Deve quindi fare riferimento a un oggetto che corrisponderà a outlive ref
, poiché la riga auto&& ref = *b;
non prevede alcun intervento temporaneo. Quindi è sicuro. Altrimenti, se *b
è un valore nominale (ad esempio il tipo di iteratore ha un operator*
che restituisce T
per un tipo di oggetto T
), la durata del temporaneo viene estesa per il resto del corpo del ciclo. In tutti i casi sei al sicuro (il caso in cui *b
è un lvalue lasciato come esercizio al lettore).
Io personalmente faccio un uso intenso di auto&&
, con o senza intervallo-per. Ma mi chiedo ogni volta se l'inizializzatore è un valore x oppure no, e se lo è, qual è la durata di ciò a cui ci si riferisce.
fonte
2012-04-03 15:50:31
Per gli utenti MSVC10 poveri a cui non è possibile usufruire dell'intervallo, la stessa domanda si applica a "BOOST_FOREACH'. –
'auto' non è mai' const'. Devi dire 'auto const &'. Inoltre, 'auto &&' non è un riferimento di rvalue, ma più di un" riferimento universale ". –
@KerrekSB Buone informazioni che 'const' non è dedotto lì. Non ho mai detto nulla sui riferimenti rvalue; v) – Potatoswatter