Newsgroup: it.comp.lang.c++
Titolo: Meglio i++ o ++i?

Salve.
Quando voglio riempire un array con passo unitario, per la variabile di
conteggio meglio scrivere:
for(i=0;i<n;i++)
oppure
for(i=0;i<n;++i)
o è uguale?
grazie

 for(i=0;i<n;++i)
Qual'e' la differenza tra i++ e ++i ?
i++ prima restituisce il valore di i, successivamente lo incrementa
++i incrementa il valore di i e restituisce il nuovo valore.
Nei cicli che hai riportato, prova ad introdurre un 
printf("%i\n", i); 
all'interno del ciclo ed uno alla fine.
Cosi' potrai verificare le tue supposizioni con il reale funzionamento :-)

 o č uguale?
La seconda *potrebbe* essere leggermente piů efficiente. Dato che
l'effetto č lo stesso e anche i caratteri da digitare sono gli stessi,
personalmente uso la seconda.
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg

In ogni caso, la soluzione piu' efficiente da un punto di vista di tempi di
esecuzione e'
for (i=n-1;i>=0;i--)
che richiede meno istruzioni assembly.
A Presto
Paolo Bardella
"Lancer" <pepp...@TOGLIEREtiscali.it> wrote in message
news:b4pohk$faf$1...@lacerta.tiscalinet.it...


 
Cerco di spiegarlo.
Effettivamente agli effetti pratici (risultato prodotto dal codice)
le due soluzioni sono equivalenti.
Perche' EMG dice che la seconda potrebbe essere piu' efficiente ?
Perche', in teoria, il compilatore arrivato in fondo
al ciclo (quando deve aggiornare i) se esegue ++i
allora deve tenere attivo solo il valore i+1 (che viene memorizzato
e "restituito") e che verra' verosimilmente utilizzato nel
corpo del ciclo nell'iterazione successiva. Se invece esegue i++
allora deve caricare i, conservare il valore (che poi non verra' mai
utilizzato) per "restituirlo" e poi incrementarlo e memorizzarlo
nuovamente dentro i.
Come giustamente ha detto EMG una soluzione *potrebbe* essere 
leggermente piu' efficiente.
Tieni pero' presente che il compilatore di solito si accorge benissimo
che il valore di i++ (o ++i) non viene utilizzato in quanto tale.
E si accorge anche
di quale valore verra' utilizzato nel ciclo. Inoltre le
variabili come sono nel codice possono tranquillamente sparire.
Per esempio andando a vedere l'assembler generato
dal ciclo for(i=0; i<100; i++) Y[i]=33;
sulla mia macchina vedo che e' uguale a for(i=0; i<100; ++i) Y[i]=44;
(in entrambi i casi la variabile i non veniva piu' usata)
il codice assembler (ritradotto in C) diventa
int *p = Y+99;
for (int i=99; i>=0; i--) {*p=33; p--;}
ovver: (solo il loop, dopo aver caricato *p in eax e 99 in ecx)
L36:
         movl $33,(%eax)
         addl $-4,%eax
         decl %ecx
         jns .L36
ciao,
g.

 che richiede meno istruzioni assembly.
Se guardi il mio messaggio di poco fa, vedi che
il compilatore si accorge da solo di questa
ottimizzazione. Cosi' noi possiamo continuare
a scrivere dei cicli che vanno logicamente in avanti...
ciao,
g.

 che richiede meno istruzioni assembly.
Ci pensa l'optimizer. E' meglio sempre scrivere del codice "logico". 
-- 
Luc.


Dimenticavo che, ovviamente, mentre il preincremento può restituire un const
reference all'oggetto il postincremento invece deve obbligatoriamente
restituire una copia del valore precedente, quindi deve invocare il
costruttore copia e in generale è meno efficiente.
A parte il tuo esempio con l'int, per qualunque altro loop (con iteratori
per esempio) conviene il preincremento.


++i in generale può essere più efficiente. Immagina di dover scrivere gli


 Ci pensa l'optimizer. E' meglio sempre scrivere del codice "logico".
Sono perfettamente d'accordo. Paga, in generale, molto più scrivere
codice leggibile che codice (magari inutilmente) ultraottimizzato.
Meglio, in ogni caso, concentrarsi sugli algoritmi.


 for(i=0;i<n;++i)
Riassumendo quello che ti e' gia' stato risposto, nel caso degli
interi non c'e' differenza, ma e' meglio abituarsi ad usare ++i,
perche' ci sono dei casi in cui la differenza puo' esserci.
Ciao,
Nicola

 Paolo Bardella
Ogni compilatore decente compilera' le 2 nello stesso modo, ma al limite
quella piu' performante dovrebbe essere --i.
Tommy

"Lancer" <pepp...@TOGLIEREtiscali.it> wrote

Si e' appena parlato di questo qualche post fa e sono stato io a fare un
accenno alla semantica di questi due costrutti.
Tommy

 wrote

Chiedo scusa ho letto in fretta il tuo messaggio e non ho visto la tua super
complicazione di un semplice for per cercare di renderla piu' veloce in
assembly.... (avevo solo capito che tu dicessi che i-- e piu' veloce di --i
ed invece tu dicevi tutta un'altra cosa...)
Il mio compilatore produce lo stesso identico codice assembly e se anche la
tua versione fosse piu' performante sarebbe una sciocchezza scriverla....
complica solo la vita. Inoltre per ottimizzare molto meglio concentrarsi
sugli algoritmi!
Ad ogni modo chiedo scusa per averti frainteso e mi scuso postandoti del
codice piu' esagerato ancora:
for (i=n; --i;)
questa infatti equivale al tuo for (i=n-1;i>=0;i--) ma e' ancora piu'
veloce! Ovvio stiamo delirando, ma evito il -1 tiro in ballo la i una sola
volta e non due. Per finire quella sola volta la tiro in ballo con --
prefisso invece che postfisso.
Voglio ricordarti pero' che la tua soluzione (e nemmeno la mia) non e'
equivalente a quella della domanda di Lancer.
Guarda l'output di questo ciclo in versione normale e poi con la tua
optimisation:
// NORMALE:
for(i=0;i<n;i++){
     cout << i << " ";
}
0 1 2 3 4 5 6 7 8 9
// TUA VERSIONE:
for(i=n-1;i>=0;i--){
     cout << i << " ";
}
9 8 7 6 5 4 3 2 1 0
Nonostante la tua versione cicli lo stesso numero di volte alcuni programmi
nei quali l'ordine e' importante potrebbero dare risultati diversi.
Basta deliri, mi sono divertito a produrre il mitico:
for (i=n; --i;)
ma .... queste sono ca**ate!
Tommy

 Paolo Bardella
Queste sono ottimizzazioni inutili e che complicano il codice, ma se ti
piacciono eccone una migliore appena prodotta:
for (i=n; --i;)
Questa e' equivalente alla tua (non a quella di lancer).
Ad ogni modo, io non la userei MAI!
Tommy

 Questa e' equivalente alla tua
con n positivo.
Tommy