Quando dovresti spostare la post-dichiarazione di un ciclo 'for' all'interno del loop attuale?

1

Con un ciclo for puoi spostare l'istruzione post vuota e spostarla nella parte inferiore del codice nel loop:

for (int i = 0; i < 10; /* empty */ ) {
    //...
    ++i;
}

Ma in questo caso non ti guadagna nulla; ancora più importante rende il codice più difficile da leggere, come ci si aspetterebbe che ++i risiedesse nella parte superiore dell'istruzione come post-dichiarazione.

Quindi quando è valido spostare la post-dichiarazione dalla sua solita posizione a qualche parte all'interno del ciclo?

Modifica Il codice che mi ha fatto riflettere su questa domanda che ho ricevuto da C ++ Primer :

for (T* p = first_free; p != elements; /* empty */)
   alloc.destroy(--p);

Qui first_free è un puntatore al primo elemento libero in una matrice di oggetti da distruggere in ordine inverso e elements è un puntatore al primo oggetto nella matrice. Qui mi sembra, valido per spostare --p da una post-dichiarazione nel ciclo, perché altrimenti dovresti riscrivere il codice in quanto tale:

for (T* p = first_free - 1; p != elements; --p)
   alloc.destroy(p);

Qui il codice si imbatterebbe in problemi se l'array non contiene effettivamente alcun oggetto, in quanto salteresti su elements e quindi causerebbe un arresto anomalo (o almeno un comportamento non definito). Ciò significa che è necessario un ulteriore controllo prima del ciclo, se la matrice contiene effettivamente o meno elementi.

    
posta gablin 25.04.2011 - 11:46
fonte

5 risposte

4

Le due forme sono semanticamente identiche (e puoi scrivere un ciclo for in un ciclo while).

Usa quello che ha più senso per i futuri lettori umani del tuo programma. A meno che non ci sia un buon motivo per farlo, dovresti stare con costruzioni ben note, in quanto rende più facile capire cosa fa il tuo codice. Di solito questo buon motivo deve essere espresso anche in un commento, quindi il lettore conosce qual è il motivo.

In questo caso particolare, la ragione per cui " posso " non è molto buona e non dovresti.

    
risposta data 25.04.2011 - 11:51
fonte
2

Non lo farei mai. Penserei di nuovo alla mia condizione di terminazione e probabilmente uso un ciclo while. Tale codice è un chiaro indicatore che la condizione di terminazione non è ottimale. E se non incasini la tua variabile i nel corpo del ciclo, puoi comunque lasciarlo in testa.

In tal modo: Non c'è motivo di scrivere un ciclo del genere in questo modo, è solo irritante.

    
risposta data 25.04.2011 - 11:51
fonte
1

Devi sempre scrivere for(int i = 0; i < end; ++i) a meno che tu non abbia una ragione per non farlo perché:

  • È più facile da leggere e rende chiara la tua intenzione.
  • Scrivendo l'incremento nella dichiarazione del ciclo for si sta dando al compilatore la migliore possibilità di ottimizzare il ciclo srotolandolo. Se si incrementa l'indice all'interno del ciclo, è molto più difficile per il compilatore risolvere se è in grado di srotolare il ciclo o meno.

Ci sono momenti in cui è necessario incrementare all'interno del loop come dimostra il tuo esempio (che è assolutamente buono), ma il punto è che dovresti farlo solo se puoi giustificarlo.

    
risposta data 25.04.2011 - 15:20
fonte
0

I cicli forici sono fondamentalmente zucchero sintattico per quando:

for (int i = 0; i < 10; i++) { doSomething(); }

è lo stesso di:

int i = 0; while (i < 10) { doSomething(); i++; }

(con l'eccezione che i ha un ambito diverso)

La ragione per usare un ciclo for è perché ti permette di mettere tutto ciò che è importante per capire le condizioni che circondano il ciclo in una posizione:

  • L'inizializzazione dell'iteratore.
  • La condizione per terminare il ciclo.
  • Il modo in cui le variabili relative alla terminazione cambiano ogni iterazione.

Ciò aumenta notevolmente la leggibilità. Quindi, se non ci si attiene a questo, non c'è praticamente alcun motivo per usare un ciclo for.

    
risposta data 25.04.2011 - 11:59
fonte
0

In primo luogo, naturalmente, c'è la possibilità che il corpo del ciclo contenga un break o continue che dovrebbe saltare questa affermazione per qualche motivo. (Nel caso di continue questi percorsi solitamente assicurano la terminazione in un modo alternativo come l'incremento di un numero diverso o l'abbassamento del limite superiore dell'iterazione)

In secondo luogo, ci sono casi in cui a volte devi fare qualcosa dopo quella dichiarazione, ma nella stessa iterazione. Ad esempio: in C ++ a volte potresti voler fare qualcosa come collection.erase(iter++) , ma poiché erase() invalida l'iteratore passato devi prima eseguire l'incremento:

Collection::iterator old = iter++;
// ... possibly a condition ...
collection.erase(old);

In questi casi di solito è una buona idea inserire l'incremento nella parte superiore del ciclo e utilizzare solo la variabile appena introdotta nel corpo.

Potrebbero esserci altri casi limite, ma tutti loro (compresi quelli menzionati sopra) dovrebbero essere relativamente rari. Nella maggior parte dei casi non è necessario nulla di ciò e la post-dichiarazione dovrebbe trovarsi nella posizione corretta nell'intestazione del ciclo.

    
risposta data 25.04.2011 - 12:10
fonte

Leggi altre domande sui tag