È utile definire una variabile all'interno di un ciclo? [chiuso]


15

Il mio istruttore una volta mi disse che non avrei dovuto definire una variabile all'interno di un ciclo , ma onestamente non capisco ancora il perché.

Quali sono gli svantaggi di questo?

Qualcuno potrebbe spiegarmelo?


7
Quale linguaggio di programmazione insegnava il tuo istruttore?
Brian,

2
Se si definisce una variabile con un tipo non primitivo in un ciclo, il programma potrebbe finire inutilmente chiamando il suo costruttore ogni volta attraverso il ciclo. Se devi solo definirlo una volta al di fuori del ciclo, fallo.
Brandin,

17
Quando hai tanta confusione su ciò che dice un istruttore, la migliore risorsa è chiedere all'istruttore. Possono darti la densa comunicazione avanti e indietro che un sito di domande e risposte non può fornire.

1
Duplicazione su più siti: differenza tra la dichiarazione di variabili prima o in loop? (e ovviamente molti, molti duplicati su quel sito per una domanda così elementare (compresi quelli che riguardano solo il C ++)).
Peter Mortensen,

2
Tale consiglio era specifico per un contesto. Per quanto riguarda lo stile personale, preferisco dichiarare le mie variabili a constmeno che non ci sia una ragione per non farlo (un'abitudine dalla programmazione funzionale). O non li modificherò e l'ottimizzatore dovrebbe rilevare quando non sono necessari, oppure lo farò e ho prevenuto un bug grave. Quando quei valori intermedi costanti sono specifici di un'iterazione del loop, ciò significa dichiararli all'interno del loop. Un'altra volta in cui è necessario dichiarare le variabili al di fuori del ciclo, tuttavia, è quando le si farà riferimento al di fuori del ciclo; ad esempio, i risultati che stai memorizzando.
Davislor,

Risposte:


42

Non è un problema da definire una variabile all'interno di un ciclo. In effetti, è una buona pratica, poiché gli identificatori dovrebbero essere limitati al più piccolo ambito possibile.

La cosa brutta è assegnare una variabile all'interno di un ciclo se potessi anche assegnarla una volta prima che il ciclo venga eseguito. A seconda della complessità della parte destra del compito, questo potrebbe diventare piuttosto costoso e potrebbe persino dominare il tempo di esecuzione del loop. Se scrivi un ciclo che utilizza lo stesso valore calcolato in tutte le iterazioni, dovresti sicuramente calcolarlo sopra il ciclo, che è più importante che ridurne al minimo l'ambito.

Per chiarire: purché compute()restituisca sempre lo stesso valore, questo

int value = compute();
while (something) {
    doSomething(value);
}

è più intelligente di questo:

while (something) {
    int value = compute();
    doSomething(value);
}

2
Come definiresti una variabile nel loop e la assegneresti prima del loop?
Masked Man

6
@ MaskedMan, penso che tu sia frainteso. Il significato di Kilian è se hai una variabile a cui è assegnato lo stesso valore durante ogni iterazione di un ciclo, ad esempio, la stessa variabile di data è impostata su 1/1/1900, la variabile dovrebbe essere dichiarata e il valore dovrebbe essere assegnato prima del ciclo.
ps2goat,

2
Non penso che ci sia stato un compilatore scritto negli ultimi venti anni (al di fuori di un corso di compilazione per studenti non laureati) che non avrebbe capito che stai assegnando lo stesso valore ad ogni iterazione e sposta quel compito fuori dal ciclo.
TMN,

14
@tmn: non lasciare mai che un compilatore faccia quello che puoi fare da solo con maggiore chiarezza del codice.
Robert Harvey,

10
@TMN, non necessariamente. Tale ottimizzazione è possibile solo se il compilatore può dimostrare che il calcolo è privo di effetti collaterali.
Paul Draper,

16

I tipi complessi hanno costruttori e distruttori non banali.

Verranno chiamati all'inizio e alla fine del corpo del loop (poiché è inizializzato e non rientra nell'ambito). Se l'inizializzazione è costosa come se fosse necessario allocare un po 'di memoria, questo dovrebbe essere evitato.

Tuttavia, per tipi banali non è un problema. L'allocazione e la deallocazione sono solo l'aggiunta e la sottrazione di un valore dal puntatore dello stack. (che verrà ottimizzato)


grazie, esattamente la risposta che stavo cercando!
gebbissimo,

6

Bene, il suo consiglio è leggermente troppo semplice (è un eufemismo).
Dopo si va tutta la strada da una buona idea su chi se ne frega e cattiva idea per impossibile .

  1. Dovresti seguirlo ogni volta che riutilizzare è più economico che distruggere il vecchio e crearne uno nuovo.

    #include <iostream>
    #include <string>
    
    int main() {
        std::string s; // Don't needlessly free the buffer
        while ((std::cin >> s))
            std::cout << s;
    }
  2. Dovresti evitarlo come una questione di stile quando non importa per le prestazioni.

    #include <stdio.h>
    #include <stdlib.h>
    int f(int, int);
    
    int main() {
        for (int i = 0; i < 100; ++i) {
            int x = rand(); // Declared here so you don't need to hunt it down.
            printf("%d => %d\n", x, f(x-1, x+i));
        }
    }
  3. Dovresti davvero evitarlo quando ha prestazioni peggiori o semantica errata.

    #include <iostream>
    #include <string>
    std::string generate(int);
    
    int main() {
        for(int i = 0; i < 100; ++i) {
            std::string s = generate(i); // Using copy-ellision here
            std::cout << s;
        }
    }
  4. Non è possibile seguirlo quando il tipo utilizzato non consente né lo scambio, né l'assegnazione di spostamenti né l'assegnazione di copie.

    #include <iostream>
    #include <puzzle>
    
    int main() {
        for (int i = 0; i < 100; ++i) {
            Puzzle x(i); // Puzzle is an immutable class. For whatever reasons.
            std::cout << x;
        }
    }

2
A seconda della tua definizione di "in un ciclo", 1 può essere modificato for (std::string s; std::cin >> s;) ...e rimanere "esterno"
Caleth,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.