2010-02-12 9 views
8

Non usare C++ da un po '. Sono stato a seconda del mio compilatore Java per fare l'ottimizzazione.C++ Dichiarare int nel ciclo for

Qual è il modo più ottimizzato per eseguire un ciclo for in C++? O è lo stesso ora con i compilatori moderm? Nei "vecchi tempi" c'era una differenza.

for (int i=1; i<=100; i++) 

O

int i; 
for (i=1; i<=100; i++) 

O

int i = 1; 
for (; i<=100; i++) 

E 'lo stesso in C?

EDIT: Okay, quindi il consenso schiacciante è quello di utilizzare il primo caso e lasciare che il compilatore ottimizzare con esso se si vuole.

+6

Questo tipo di domanda è davvero un brutto segno ... –

+0

+1 Per chiedere questo, solo così il mito può essere debuffato – Andres

risposta

12

Direi che cose banali come questa sono probabilmente ottimizzate dal compilatore, e non dovresti preoccuparti di loro. La prima opzione è la più leggibile, quindi dovresti usarla.

MODIFICA: aggiungendo quali altre risposte hanno detto, c'è anche la differenza che se si dichiara la variabile nell'inizializzatore del ciclo, essa smetterà di esistere dopo la fine del ciclo.

+2

Per quanto riguarda la tua modifica, questo dipende dal compilatore. Ho visto almeno un compilatore (MSVC++ 6.0) in cui la variabile non cessa di esistere dopo la fine del ciclo. –

+2

@Jeff I compilatori conformi allo standard limitano l'ambito di _i_ il ciclo for, ma ci sono compilatori precedenti, come MSVC++ 6.0, che non lo fanno. Quindi, se stai usando un compilatore più vecchio, è qualcosa a cui prestare attenzione. Per lo standard della lingua, tuttavia, l'ambito è limitato al ciclo for. I compilatori recenti dovrebbero comportarsi correttamente a tale riguardo. –

+0

Su MSVC, è possibile utilizzare l'hasc "#define for if (0) {} else per" per ottenere il comportamento corretto. Ah sì, i bei vecchi tempi ... –

4

È lo stesso. Il compilatore li ottimizzerà per la stessa cosa.

Anche se non erano uguali, la differenza rispetto al corpo reale del loop sarebbe trascurabile. Non dovresti preoccuparti delle micro-ottimizzazioni come questa. E non dovresti fare micro-ottimizzazioni a meno che tu non stia eseguendo il profiling delle prestazioni per vedere se effettivamente fa la differenza.

3

È lo stesso in termini di velocità. Il compilatore ottimizzerà se non si ha un uso successivo di i.

In termini di stile, inserisco la definizione nel costrutto del ciclo, in quanto riduce il rischio di conflitto se ne definisci un altro dopo.

9

La differenza è lo scopo.

for(int i = 1; i <= 100; ++i) 

è generalmente preferibile perché quindi la portata di i è limitata al ciclo for. Se lo dichiari prima del ciclo for, allora continua ad esistere dopo che il ciclo for è terminato e potrebbe scontrarsi con altre variabili. Se lo stai usando solo nel ciclo for, non c'è motivo di lasciarlo esistere più a lungo.

+0

In alcuni dei vecchi compilatori, lo scope di i, è alla fine della funzione. spostando l'int, out of the loop ti tiene bene con altri compilatori. – EvilTeach

+0

@EvilTech Solo i compilatori più vecchi e non conformi avranno questo problema. Quindi, a meno che tu non pensi che ci siano buone probabilità che il tuo codice venga usato con un compilatore di questo tipo, non me ne preoccuperei. Se si tratta di un problema, il problema verrà risolto inserendo un paio di parentesi graffe aggiuntive attorno al ciclo for. –

1

Non preoccuparti delle micro-ottimizzazioni, lascia che sia il compilatore a farlo. Scegli quale è più leggibile. Si noti che la dichiarazione di una variabile all'interno di un'istruzione di inizializzazione for circoscrive la variabile all'istruzione for (C++ 03 § 6.5.3 1), sebbene il comportamento esatto dei compilatori possa variare (alcuni consentono di scegliere). Se il codice al di fuori del ciclo utilizza la variabile, dichiararlo al di fuori del ciclo. Se la variabile è veramente locale al ciclo, dichiararla nell'inizializzatore.

-1

È lo stesso.

1

È già stato detto che la differenza principale tra i due è l'ambito.Assicurati di capire come il compilatore gestisce il campo di applicazione di un int dichiarata come

for (int i = 1; ...;...) 

So che quando si utilizzano MSVC++ 6, i è ancora nel campo di applicazione al di fuori del ciclo, proprio come se si fosse dichiarato prima del ciclo . Questo comportamento è diverso da VS2005 e dovrei controllare, ma penso che l'ultima versione di gcc che ho usato. In entrambi i compilatori, quella variabile era solo nell'ambito del ciclo.

+0

Questo è un bug noto in VC++ 6. Se davvero ti interessa racchiudere il ciclo for con un altro set di parentesi graffe. – jmucchiello

5

Diciamo che il poster originale aveva un ciclo che desiderava davvero ottimizzare - ogni istruzione contava. Come possiamo capire - empiricamente - la risposta alla sua domanda?

gcc ha almeno un interruttore utile, se usato in modo non comune, '-S'. Scarica la versione del codice assembly del file .c e può essere utilizzato per rispondere a domande come le posizioni OP. Ho scritto un semplice programma:

int main() 
{ 
    int sum = 0; 

    for(int i=1;i<=10;++i) 
    { 
     sum = sum + i; 
    } 
    return sum; 
} 

e corse: gcc -O0 -std=c99 -S main.c, creando la versione montaggio del programma principale. Ecco il contenuto della main.s (con alcuni dei fluff rimosso):

movl $0, -8(%rbp) 
    movl $1, -4(%rbp) 
    jmp  .L2 
.L3: 
    movl -4(%rbp), %eax 
    addl %eax, -8(%rbp) 
    addl $1, -4(%rbp) 
.L2: 
    cmpl $10, -4(%rbp) 
    jle  .L3 

Non è necessario essere un esperto di assemblaggio per capire cosa sta succedendo. movl sposta valori, addl aggiunge oggetti, cmpl confronta e jle sta per 'salta se minore di', $ è per costanti. Sta caricando 0 in qualcosa - che deve essere 'somma', 1 in qualcos'altro - ah, 'i'! Un salto a L2 dove facciamo il confronto a 10, salta a L3 per fare l'add. Riempi fino a L2 per il confronto di nuovo. Neat! A per ciclo.

cambiare il programma per:

int main() 
{ 
    int sum = 0; 
    int i=1; 
    for(;i<=10;++i) 
    { 
     sum = sum + i; 
    } 
    return sum; 
} 

Eseguire nuovamente gcc e il gruppo risultante saranno molto simili. Ci sono alcune cose in corso con i numeri delle linee di registrazione, quindi non saranno identiche, ma l'assemblaggio finisce per essere lo stesso. Lo stesso risultato con l'ultimo caso. Quindi, anche senza ottimizzazione, il codice è quasi lo stesso.

Per divertimento, rieseguire gcc con '-O3' anziché '-O0' per abilitare l'ottimizzazione e guardare il file .s.

main: 
movl $55, %eax 
ret 

gcc non solo capito che stavamo facendo un ciclo, ma anche rese conto che doveva essere eseguito un numero costante di volte ha fatto il circuito per noi al momento della compilazione, buttato fuori 'i' e 'sum' e ho codificato la risposta in modo sicuro - 55! È VELOCE, anche se un po 'forzato.

Morale della trama? Passa il tuo tempo a garantire che il tuo codice sia pulito e ben progettato. Codice per leggibilità e manutenibilità. I ragazzi che vivono su Mountain Dew e Cheetos sono molto più intelligenti di noi e si sono presi cura di molti di questi semplici problemi di ottimizzazione per noi. Divertiti!

1
for(int i = 1; i <= 100; ++i) 

Questo è più facile da leggere, ad eccezione di ANSI C/C89 dove è valido.