Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Move

68 views
Skip to first unread message

Emanuele Merlo

unread,
Nov 28, 2017, 5:25:38 AM11/28/17
to
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?

Emanuele Merlo

unread,
Nov 28, 2017, 5:26:16 AM11/28/17
to
"push_back"

fma...@gmail.com

unread,
Nov 28, 2017, 10:33:08 AM11/28/17
to
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!

Enrico Maria Giordano

unread,
Nov 28, 2017, 10:44:37 AM11/28/17
to


Il 28/11/2017 16:33, fma...@gmail.com ha scritto:

>> C'è differenza tra approccio 1 e 2? ce n'è uno sbaglio o uno preferibile?
>
> 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.

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

fma...@gmail.com

unread,
Nov 28, 2017, 11:06:51 AM11/28/17
to
On Tuesday, November 28, 2017 at 10:44:37 AM UTC-5, Enrico Maria Giordano wrote:
> Il 28/11/2017 16:33, fma...@gmail.com ha scritto:
>
> >> C'è differenza tra approccio 1 e 2? ce n'è uno sbaglio o uno preferibile?
> >
> > 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.
>
> Dici questo perché il compilatore ottimizzerà evitando l'oggetto
> temporaneo, se non usato dopo, giusto?
>

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!

Emanuele Merlo

unread,
Nov 28, 2017, 11:17:36 AM11/28/17
to

> 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.

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.

fma...@gmail.com

unread,
Nov 28, 2017, 11:25:33 AM11/28/17
to
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!

Enrico Maria Giordano

unread,
Nov 28, 2017, 12:41:52 PM11/28/17
to


Il 28/11/2017 17:06, fma...@gmail.com ha scritto:

> 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.

Capisco. Mi sa che sono rimasto un po' indietro con il C++... :-(

fma...@gmail.com

unread,
Nov 28, 2017, 1:00:55 PM11/28/17
to
On Tuesday, November 28, 2017 at 12:41:52 PM UTC-5, Enrico Maria Giordano wrote:
> Il 28/11/2017 17:06, fma...@gmail.com ha scritto:
>
> > 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.
>
> 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!

Enrico Maria Giordano

unread,
Nov 28, 2017, 1:21:49 PM11/28/17
to


Il 28/11/2017 19:00, fma...@gmail.com ha scritto:

>> 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.

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

enoquick

unread,
Nov 28, 2017, 11:06:34 PM11/28/17
to
Il 28/11/2017 04:25, Emanuele Merlo ha scritto:
> Consideriamo quest'esempio:
>
>
> vector<UnOggettoGrossoComplesso> mioVettore;
>
>
> // #1
> UnOggettoGrossoComplesso mioOggetto(QualcheParametro);
> mioVettore.push_bach(move(mioOggetto));
>

qui forzi mioOggetto ad essere un rvalue grazie a move
Dopo il push back mioOggetto deve trovarsi in uno stato valido in modo
che il suo distruttore funzioni correttamente quando verra
chiamato,sempre se esiste il costruttore di move di
UnOggettoGrossoComplesso altrimenti fa la copia


> // #2
> mioVettore.push_bach(move(UnOggettoGrossoComplesso(QualcheParametro)));
>

Qui la move non serve visto che std::vector ha gia push_back(&&) e
UnOggettoGrossoComplesso e' un rvalue (e anche qui deve avere il
costruttore di move altrimenti fa la copia)



>
> C'è differenza tra approccio 1 e 2? ce n'è uno sbaglio o uno preferibile?
>

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

Emanuele Merlo

unread,
Nov 29, 2017, 4:13:00 AM11/29/17
to
Il giorno martedì 28 novembre 2017 19:21:49 UTC+1, Enrico Maria Giordano ha scritto:

[...]
> 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.

Enrico Maria Giordano

unread,
Nov 29, 2017, 4:25:23 AM11/29/17
to


Il 29/11/2017 05:06, enoquick ha scritto:

> Ricorda solo che std::move forza un oggetto ad essere  un rvalue
> 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.

Emanuele Merlo

unread,
Nov 29, 2017, 5:07:14 AM11/29/17
to
Il giorno mercoledì 29 novembre 2017 10:25:23 UTC+1, Enrico Maria Giordano ha scritto:

> 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.

"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]

Enrico Maria Giordano

unread,
Nov 29, 2017, 5:24:05 AM11/29/17
to


Il 29/11/2017 11:07, Emanuele Merlo ha scritto:

>> 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.
>
> "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."

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?

Emanuele Merlo

unread,
Nov 29, 2017, 10:28:46 AM11/29/17
to
Il giorno mercoledì 29 novembre 2017 11:24:05 UTC+1, Enrico Maria Giordano ha scritto:


> 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?

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

Enrico Maria Giordano

unread,
Nov 29, 2017, 10:37:14 AM11/29/17
to


Il 29/11/2017 16:28, Emanuele Merlo ha scritto:

>> 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?
>
> 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.

enoquick

unread,
Nov 29, 2017, 12:47:02 PM11/29/17
to
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


Enrico Maria Giordano

unread,
Nov 29, 2017, 1:08:43 PM11/29/17
to


Il 29/11/2017 18:47, enoquick ha scritto:

> 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

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?

fma...@gmail.com

unread,
Nov 29, 2017, 1:20:27 PM11/29/17
to
On Wednesday, November 29, 2017 at 5:07:14 AM UTC-5, Emanuele Merlo wrote:
> "Ogni espressione C++ è un lvalue o un rvalue. [...]
>

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!

Enrico Maria Giordano

unread,
Nov 29, 2017, 1:31:02 PM11/29/17
to


Il 29/11/2017 19:20, fma...@gmail.com ha scritto:

>> "Ogni espressione C++ è un lvalue o un rvalue. [...]
>
> 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

Azz!... :-(

Emanuele Merlo

unread,
Nov 30, 2017, 4:09:19 AM11/30/17
to
Il giorno mercoledì 29 novembre 2017 19:20:27 UTC+1, fma...@gmail.com ha scritto:


> 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

Thanks!

fma...@gmail.com

unread,
Nov 30, 2017, 10:39:11 AM11/30/17
to
On Wednesday, November 29, 2017 at 1:31:02 PM UTC-5, Enrico Maria Giordano wrote:
> Il 29/11/2017 19:20, fma...@gmail.com ha scritto:
>
> >> "Ogni espressione C++ è un lvalue o un rvalue. [...]
> >
> > 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
>
> Azz!... :-(
>

:) 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!

Enrico Maria Giordano

unread,
Nov 30, 2017, 10:48:11 AM11/30/17
to


Il 30/11/2017 16:39, fma...@gmail.com ha scritto:

> Spero sia un po' più chiaro :)

Sì, grazie.

enoquick

unread,
Nov 30, 2017, 9:58:39 PM11/30/17
to
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



enoquick

unread,
Nov 30, 2017, 10:14:02 PM11/30/17
to
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


enoquick

unread,
Nov 30, 2017, 10:22:46 PM11/30/17
to
Ma una espressione puo essere categorizzata in glvalue o rvalue secondo
la nuova categorizzazione

Secondo la vecchia lvalue o rvalue

Enrico Maria Giordano

unread,
Dec 1, 2017, 4:08:29 AM12/1/17
to


Il 01/12/2017 03:58, enoquick ha scritto:

> 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

Grazie.

fma...@gmail.com

unread,
Dec 1, 2017, 5:50:13 PM12/1/17
to
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!

enoquick

unread,
Dec 1, 2017, 11:11:38 PM12/1/17
to
Ma e' proprio dal doc. di cui hai postati l'url che si ricava una cosa
del genere.
Non e' mia invenzione

fma...@gmail.com

unread,
Dec 2, 2017, 4:33:36 PM12/2/17
to
> 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!

Enrico Maria Giordano

unread,
Dec 2, 2017, 4:48:54 PM12/2/17
to


Il 02/12/2017 22:33, fma...@gmail.com ha scritto:

> 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 :)

Grazie, me lo leggo senz'altro.

Enrico Maria Giordano

unread,
Dec 3, 2017, 5:56:22 AM12/3/17
to


Il 02/12/2017 22:48, Enrico Maria Giordano ha scritto:

>> 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 :)
>
> 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++?

fma...@gmail.com

unread,
Dec 4, 2017, 5:32:58 AM12/4/17
to
On Sunday, December 3, 2017 at 5:56:22 AM UTC-5, Enrico Maria Giordano wrote:
> Il 02/12/2017 22:48, Enrico Maria Giordano ha scritto:
>
> >> 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 :)
> >
> > 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!

Enrico Maria Giordano

unread,
Dec 4, 2017, 6:06:01 AM12/4/17
to


Il 04/12/2017 11:32, fma...@gmail.com ha scritto:

> 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.

Lo cerco, grazie.
0 new messages