2011-01-23 3 views
33

Mi chiedevo che cosa utilizzare un elemento di riferimento rvalue haUso di membri di riferimento di rvalue?

class A { 
    // ... 
    // Is this one useful? 
    Foo &&f; 
}; 

Ha ha vantaggi o svantaggi rispetto ad un elemento di riferimento lvalue? Qual è l'uso principale di esso?

+0

@GMan non so il motivo per cui è meglio che solo dicendo 'modello struct ACW {T & t; acw (T && t): t (t) {} modello operatore U() {return static_cast (std :: forward (t)); }} '. Cosa guadagni avendo il membro 't' un riferimento di valore? A proposito, penso che n3225 dice che un costruttore di copie predefinito è definito come cancellato se si hanno membri di riferimento di rvalue. Quindi non puoi ancora copiare un 'auto_cast_wrapper ' ma muoverlo solo :) –

+0

Niente, voglio solo dire che l'ho usato lol. E hm, buono a sapersi. Dovrò ripararlo più tardi. – GManNickG

+0

@GMan Ohh lo vedo ora! Grazie per la presentazione, penso che sia uno strumento interessante da usare. –

risposta

21

Ho visto un caso d'uso molto motivante per i membri di dati di riferimento rvalue, ed è in C++ 0x progetto:

template<class... Types> 
tuple<Types&&...> 
forward_as_tuple(Types&&... t) noexcept; 

Effetti: Costruisce una tupla di riferimenti agli argomenti in t adatto per l'inoltro come argomenti a una funzione. Poiché il risultato potrebbe contenere variabili, un programma deve garantire che il valore restituito da questa funzione non sia superiore a nessuno dei suoi argomenti. (ad esempio, il programma dovrebbe tipicamente non memorizzare il risultato in una variabile denominata ).

Reso: tuple<Types&&...>(std::forward<Types>(t)...)

La tupla ha membri di dati di riferimento rvalue quando rvalues ​​vengono utilizzati come argomenti per forward_as_tuple, e altrimenti ha membri di dati di riferimento lvalue.

Ho trovato forward_as_tuple successivamente utile quando è necessario catturare argomenti variadici, inoltrarli perfettamente imballati come una tupla e ri-espanderli più tardi al punto di inoltro a un functor. Ho usato forward_as_tuple in questo stile in sede di attuazione di una versione migliorata del tuple_cat proposto nel LWG 1385:

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1385

+0

Puoi spiegare come viene gestita la durata del rvalue in questo caso ?La distruzione di valore è in qualche modo estesa fino al punto "successivo" quando viene utilizzato il valore di rvalue? –

+1

grazie per la tua risposta e spiegazione. La domanda è venuta fuori quale sia il requisito "Poiché il risultato può contenere riferimenti a variabili temporanee, un programma deve garantire che il valore di ritorno di questa funzione non sopravviva a nessuno dei suoi argomenti." implica un programma. Uno snippet come questo ha un comportamento indefinito? '{auto x = forward_as_tuple (0); } ', perché viola il requisito obbligatorio nella sezione effetti? Perché è necessario un tale requisito? Una tupla contenente riferimenti non aggiornati non può essere distrutta? –

+1

Il client di forward_as_tuple deve garantire che il risultato sia "consumato" prima del punto di sequenza. I primi esempi del suo utilizzo si trovano in: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3059.pdf ma in questo documento la funzione è chiamata pack_arguments invece di forward_as_tuple. L'uso in N3059 mostra la tupla di riferimenti creati, passati a un'altra funzione, consumati (usati) e destrutturati, in quest'ordine. –

12

In base a Stephan T. Lavavej, i membri dei dati di riferimento di rvalue non usano.

La cosa che ho visto fare ai programmatori quando ottengono referenze di valore è che, iniziano a diventare un po 'pazzi, perché sono così potenti. Cominciano a dire "Oh, avrò membri di dati di riferimento di rvalore, avrò variabili di riferimento di riferimento rvalue, avrò valori di riferimento di riferimento di rvalue!" E poi scrivono il codice come questo: [...]

+0

Grande serie, ci vorrà vedere tutto, ma non vedo l'ora :) –

+17

Ci vorranno circa 10 anni prima di capire come utilizzare correttamente i riferimenti di valore. –

+0

Immagino che i programmatori siano confusi riguardo ai riferimenti rvalue e pensano che aumenteranno magicamente la durata dell'oggetto (quindi i valori di ritorno dei valori di riferimento), mentre in realtà non ha nulla a che fare con la durata, come spiegato nel video. –

2

Pensando solo ad alta voce qui, ma non avrebbe un uso in funtori? Il costruttore è spesso usato per "currying", vincolando alcuni parametri in anticipo, prima della chiamata della funzione effettiva.

Quindi, in questo contesto, il membro della classe è solo un punto di partenza (o una chiusura implementata manualmente) per la prossima chiamata di funzione, e non vedo alcun motivo per cui un riferimento di rvalue non sarebbe significativo lì.

Ma nelle classi "normali" non-functor, non vedo molto.

+0

Perché il downvote? – jalf

+0

Come in questo caso un riferimento di rvalue è migliore di un 'const &' (o solo un riferimento normale se è necessario modificarlo)? –

+0

Per lo stesso motivo si potrebbe altrimenti voler passare un riferimento rvalue a una funzione: essere in grado di * spostarsi * da esso. – jalf

2
class A { 
    // ... 
    // Is this one useful? 
    Foo &&f; 
}; 

In questo caso specifico, non vi è alcun motivo per utilizzare un riferimento di rvalue. Non ti compra nulla che non avresti potuto fare prima.

Tuttavia, è possibile definire i membri dati con tipi parametrizzati. std :: tuple supporterà i membri dei dati di riferimento lvalue e rvalue, per esempio. In questo modo è possibile codificare la categoria di valore di un'espressione che potrebbe rivelarsi utile per "inoltro perfetto ritardato". La bozza standard include anche un modello di funzione del modulo

template<class Args...> 
tuple<Args&&...> pack_arguments(Args&&...args); 

Ma sinceramente non sono sicuro della sua utilità.

+0

Questo post spiega un possibile utilizzo di forward_as_tuple o pack_arguments: http://cpptruths.blogspot.com/2012/06/perfect-forwarding-of-parameter-groups.html – Sumant