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

14

Una volta il mio istruttore mi ha detto che non dovrei definire una variabile all'interno di un ciclo , ma sinceramente non capisco perché.

Quali sono gli svantaggi di questo?

Qualcuno potrebbe spiegarmelo?

    
posta user3260672 08.09.2015 - 16:32
fonte

3 risposte

38

Non è un problema per definire una variabile all'interno di un ciclo. In effetti, è una buona pratica, dal momento che gli identificatori dovrebbero essere confinati al più piccolo ambito possibile.

Ciò che è male è assegnare una variabile all'interno di un ciclo, se puoi anche assegnarlo una volta prima il ciclo viene eseguito. A seconda della complessità del lato destro del compito, questo potrebbe diventare piuttosto costoso e potrebbe persino dominare il tempo di esecuzione del ciclo. Se scrivi un ciclo che utilizza lo stesso valore calcolato in tutte le iterazioni, dovresti sicuramente calcolarlo sopra il ciclo - che è più importante che minimizzare il suo ambito.

Per chiarire: finché compute() restituisce sempre lo stesso valore, questo

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

è più intelligente di questo:

while (something) {
    int value = compute();
    doSomething(value);
}
    
risposta data 08.09.2015 - 16:42
fonte
13

I tipi complessi hanno costruttori e distruttori non banali.

Questi verranno richiamati all'inizio e alla fine del corpo del ciclo (poiché è inizializzato e esce dall'ambito). Se l'inizializzazione è costosa, come se fosse necessario allocare memoria, dovrebbe essere evitata.

Tuttavia per tipi banali non c'è problema. L'allocazione e la deallocazione stessa stanno semplicemente aggiungendo e sottraendo un valore dal puntatore dello stack. (che verrà ottimizzato)

    
risposta data 08.09.2015 - 16:45
fonte
5

Bene, il suo consiglio è leggermente troppo semplice (è un eufemismo).
Segue tutto da una buona idea su chi cura e cattiva idea a impossibile .

  1. Dovresti seguirlo ogni volta che riutilizzare costa meno 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 questione di stile quando non ha importanza 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. veramente dovrebbe essere evitato quando ha prestazioni peggiori o semantica sbagliata.

    #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. Tu non puoi seguirlo quando il tipo usato non consente né lo scambio, né l'assegnazione dello spostamento né l'assegnazione della copia.

    #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;
        }
    }
    
risposta data 08.09.2015 - 21:34
fonte