Newsgroup: it.comp.lang.c++
Titolo: Move

Consideriamo quest'esempio:
 
 
vector<UnOggettoGrossoComplesso> mioVettore;
 
 
// #1
UnOggettoGrossoComplesso mioOggetto(QualcheParametro);
mioVettore.push_bach(move(mioOggetto));
 
// #2
mioVettore.push_bach(move(UnOggettoGrossoComplesso(QualcheParametro)));
 
 
C'è differenza tra approccio 1 e 2? ce n'è uno sbaglio o uno preferibile?


"push_back"


Direi che sono identici, a patto che nel #1 poi non si usi più mioOggetto
dopo il push. Se hai paura che questo accada (per errori o dimenticanze)
vai di #2.
 
Ciao!

 vai di #2.
 
Dici questo perché il compilatore ottimizzerà evitando l'oggetto 
temporaneo, se non usato dopo, giusto?
 
EMG
 
--
http://www.emagsoftware.it
 
http://www.emagsoftware.it/emgmusic
 
http://www.emagsoftware.it/spectrum
 
http://www.emagsoftware.it/tbosg
 

 
 
Perché il move constructor di UnOggettoGrossoComplesso potrebbe lasciare
mioOggetto in uno stato non valido. Nel caso #2 l'oggetto viene distrutto
immediatamente, quindi non c'è il rischio di riusarlo per sbaglio.
 
Ciao!

 immediatamente, quindi non c'è il rischio di riusarlo per sbaglio.
 
L'ho chiesto perché in un'applicazione reale, il metodo 1 ha funzionato, il metodo 2 causava un'eccezione. Essendo una manutenzione evolutive su codice non mio, non ho avuto modo di capire a fondo perché. Mi chiedevo se uno dei due approcci potesse essere sbagliato, ma a quanto pare no.


Sintatticamente e concettualmente è giusto, bisognerebbe vedere che eccezione
avevi. Con questo tipo di "pattern" è facile (almeno per me) incappare in
errori sulla ownership delle risorse.
 
Ciao!

 immediatamente, quindi non c'è il rischio di riusarlo per sbaglio.
 
Capisco. Mi sa che sono rimasto un po' indietro con il C++... :-(


 
 
Sì, questa è roba C++11.
Immagino anche te, come me, e forse come la maggior parte dei "vecchi"
programmatori C++, preferiamo un semplice vettore di puntatori invece di
tutta una svaccata di magheggi di cui non abbiamo mai sentito la mancanza.
Son gusti.
 
Ciao!

 Son gusti.
 
Un po' è così e un po' la mancanza di tempo...


 
 
Nessuno
Ricorda solo che std::move forza un oggetto ad essere  un rvalue
Se e' gia un rvalue std::move non serve

 Un po' è così e un po' la mancanza di tempo...
 
Io sono "vecchio" ma alcune cose nuove del c++11 le trovo una figata. 
A parte lavorare coi puntatori, la move semantic se gestita correttamente evita un mucchio di copie inutili in modo trasparente. 
Il difficile è conoscere il comportamento delle nuove funzionalità in tutte le combinazioni possibili. Penso ci si arrivi solo con l'esperienza.

 Se e' gia un rvalue std::move non serve
 
Mi spieghi cosa intende esattamente il C++ con essere "un rvalue" in 
questo caso? Come fa un oggetto a non essere un rvalue? Capisco che 
possa non essere un lvalue (se è un oggetto a sola lettura) ma mi sfugge 
come possa un oggetto non essere un valore assegnabile.


 come possa un oggetto non essere un valore assegnabile.
 
"Ogni espressione C++ è un lvalue o un rvalue. Un lvalue fa riferimento a un oggetto che viene mantenuto oltre una singola espressione. È possibile considerare un lvalue come un oggetto che ha un nome. Tutte le variabili, incluse le variabili non modificabili (const), sono lvalue. Un rvalue è un valore temporaneo che non viene mantenuto oltre l'espressione che lo utilizza."
[
https://msdn.microsoft.com/it-it/library/f90831hc.aspx
]

 mantenuto oltre l'espressione che lo utilizza."
 
Sicuramente diverso da come lo intendevo io. Finora ho sempre ritenuto 
che un left value fosse un'espressione che si può mettere (anche) alla 
sinistra dell'assegnazione mentre un right value un'espressione che può 
stare solo alla destra dell'assegnazione. Non è più questo il 
significato comunemente accettato?


 significato comunemente accettato?
 
Sinceramente non saprei, non mi ero mai posto il problema finchè non ho affrontato le move semantics :)) quindi il primo concetto che ho avuto è quello spiegato sopra

 Sinceramente non saprei, non mi ero mai posto il problema finchè non ho affrontato le move semantics :)) quindi il primo concetto che ho avuto è quello spiegato sopra
 
Ok.



Un rvalue e' un oggetto che sta alla destra di una assegnazione,e' un 
temporaneo che poi viene distrutto alla fine dell' istruzione di cui fa 
parte
 
void f(T&&);
void f(const T&)
 
 
f(T())
 
 
qui l'oggetto di tipo T e' un rvalue (e un temporaneo) e visto che 
esiste f(T&&) puo essere spostato
 
void g(const T&);
 
g(T())
 
qui l'oggetto di tipo T e' sempre un rvalue (e temporaneo) ma non 
esistendo un g(T&&) viene fatta la copia
 
 
auto a=....
 
a e' un lvalue
 
 
Tutte questo,naturalmente, senza tenere conto delle ottimizzazioni che 
puo fare il compilatore:
 
 
ES:
 
 
T f() {  return T(); }
 
Qui,senza ottimizzazioni,viene fatta la copia
Ma con le ottimizzazioni il compilatore puo eliminare la copia
 
 

 parte
 
Ah, ok. Quindi
 
int n = 1;
 
1 è un rvalue. Mentre
 
int m = n;
 
n non è un rvalue ma un lvalue. E
 
int m = std::move( n );
 
rende n un rvalue che quindi dopo questa istruzione non deve essere più 
utilizzato. Ho capito bene?



 
No, non è così da un po'.
Da C++11 ci sono rvalues, lvalues, xvalues, glvalues, e prvalues. E tutto
per stare dietro a questa roba del move.
Uno dei tanti riferimenti:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3055.pdf
 
 
Ciao!

 
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3055.pdf
 
 
Azz!... :-(


 
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3055.pdf
 
 
Thanks!

 
 
:) Non ti preoccupare, tutte queste definizioni sono utili solo per chi
scrive le specifiche e agli implementers. Al programmatore normale non
importa molto come si chiami questo o quello, o cosa debba fare il
compilatore in casi borderline.
 
Anche fosse, il concetto non è difficile: invece di dividere le espressioni
in sinistra e destra, le dividi secondo due proprietà: identificabile
(e.g. variabili, puntatori, ma non roba temporanea) e spostabile.
Hai roba identificabile e spostabile, roba identificabile e non spostabile,
roba non identificabile e basta, etc.
La "genialata" è stata che invece di usare nomi decenti per la nuova
categorizzazione delle espressioni hanno riusato i vecchi lvalue/rvalue
con significati nuovi :(
 
Comunque, tutta la roba spostabile è rvalue (se è "pura", cioè temporanea
o non identificabile, in altra parole come ce l'abbiamo sempre avuta in mente,
prvalue).
Lvalue sono le cose identificabili e non spostabili.
Le robe identificabili e spostabili son queste nuove strane che vengono
fuori con riferimenti modificabili, e l'hanno chiamate xvalue.
L'ultima categoria, glvalue, è solo il "genitore" di lvalue e xvalue, e sta
lì solo per completare lo schemino.
 
Spero sia un po' più chiaro :)
 
Ciao!

 Spero sia un po' più chiaro :)
 
Sì, grazie.



Si,dici bene
std::move al contrario di quello che sembrerebbe il suo nome,in realta 
non sposta un bel niente
Trasforma solo un lvalue in rvalue in modo che possa essere applicata 
una move invece di una copy
Un lvalue non viene mai spostato ma copiato,per spostarlo occorre 
forzare con std::move
 
 
 


Per chi e' interessato consiglio il libro di Scott Meyers 
"Programmazione C++ Moderna" che spiega le novita di C++11 e C++14
ed e' scritto molto bene
 
 


Ma una espressione puo essere categorizzata in glvalue o rvalue secondo 
la nuova categorizzazione
 
Secondo la vecchia lvalue o rvalue
 

 forzare con std::move
 
Grazie.



Leggi il mio reply a EMC: cambiando il significato, hanno cercato di
"forzare" i vecchi nomi ad avere due delle vecchie proprietà:
- un espressione può essere o lvalue o rvalue.
- se un espressione è lvalue non può essere rvalue, e viceversa.
Questo però non dice nulla su quello che i nomi rappresentano, tant'è vero
che la prima non sono riusciti a portarla a termine (avrebbero dovuto
cambiare troppe parti dello standard precedente per allineare i termini).
 
Cerco di essere preciso perché, anche se son sicuro che tu personalmente
ti sei letto lo standard, molti di quelli che leggono qui hanno, come la
avevo anch'io fino a poco tempo fa, un po' di difficoltà ad abituarsi alle
nuove terminologie.
 
In ogni caso avevo letto un documento scritto da Stroustrup stesso a
riguardo, ma purtroppo non lo ritrovo. Spiegava bene tutto questo bailamme.
 
Ciao!


Ma e' proprio dal doc. di cui hai postati l'url che si ricava una cosa 
del genere.
Non e' mia invenzione
 


 
Trovato:
http://www.stroustrup.com/terminology.pdf
 
 
Non dice molto di più, ma è interessante leggere come ci sono arrivati,
specialmente dal punto di vista di Stroustrup :)
 
 
Ciao!

 specialmente dal punto di vista di Stroustrup :)
 
Grazie, me lo leggo senz'altro.


 Grazie, me lo leggo senz'altro.
 
Letto. Mah... Certo, il punto centrale della questione è l'introduzione 
del concetto di move. Mi pare sia quello che abbia reso necessario il 
nuovo naming, almeno a detta di alcuni (non so quanti) partecipanti alla 
costruzione dello standard. C'è un documento altrettanto sintetico e 
chiaro che spieghi il concetto di move così come inteso dallo standard C++?


 
 
Non so, ma giusto cercando "move semantics" su google trovi subito un sacco
di roba abbastanza ben scritta. Alla fine il concetto viene abbastanza
naturale, IMHO.
 
Ciao!

 naturale, IMHO.
 
Lo cerco, grazie.
