For loop all'interno delle proprie parentesi graffe


117

Mi sono imbattuto in questo layout for-loop:

#include <iostream>
int main()
{
    {
        for (int i = 0; i != 10; ++i)
        {
            std::cout << "delete i->second;" << std::endl;
        }
    }

    {
        for (size_t i = 0; i < 20; ++i)
        {
            std::cout << "delete m_indices[i];" << std::endl;
        }
    }
    return 0;
}

Mi chiedevo a cosa serva questo strato extra di parentesi graffe? Questo appare alcune volte nella nostra base di codice.


47
Sono completamente superflui nello snippet di codice che hai pubblicato
EdChum

25
quali compilatori sono stati utilizzati con questo codice? Nello specifico è stato utilizzato VS 6?
UKMonkey

5
@EdNorman ora con la tua modifica è molto più chiaro. Sembra che la risposta corretta sia quella fornita da UKMonkey. Con il moderno compilatore C ++ puoi semplicemente eliminare le parentesi graffe.
Jabberwocky

8
In alternativa, potrebbe essere generato un codice (sospirò qualcuno che stava solo facendo i conti con Rhapsody)
Mawg dice reintegrare Monica

4
Una possibile ragione è se il codice una volta avesse (o dovrebbe avere in futuro) direttive parallele OpenMP.
jamesqf

Risposte:


286

C'era una volta, molte lune fa, VS6 esisteva ed era popolare. Tuttavia non è riuscito a conformarsi a un certo numero di standard C ++; che era ragionevole all'epoca in quanto fu rilasciato poco prima (nello stesso anno) che lo standard fosse ufficialmente rilasciato; comunque aderiva alla bozza della norma, per quanto ne so.

Uno degli standard che è cambiato tra la bozza e lo standard ufficiale, è stata la durata delle variabili del ciclo for create nella prima sezione; portando al codice seguente che non riesce a compilare

{
    for (int i=0; i<1; ++i){}
    for (int i=0; i<2; ++i){}
}

perché è istato ridefinito dal secondo ciclo for.

Mentre altri compilatori soffrivano di questo bug; Sottolineo quella VS6 perché è rimasta l'unica versione di visual studio per diversi anni dopo il rilascio dello standard, ma non ha mai rilasciato un aggiornamento per questo particolare problema; il che significa che ha avuto un impatto più significativo.

Una soluzione a questo è forzare l'intero ciclo for nel proprio ambito come hai mostrato.


49
Non c'è bisogno di trovare VS6 per vedere che @bolov, imposta "Force Conformance in For Loop Scope" su "No" in VS2015 e divertiti ;-)
alain

5
@alain "l'opzione 'Zc: forScope-' è stata deprecata e verrà rimossa in una versione futura" e si compila senza problemi ... Sono triste
bolov

7
Anche GCC precedente alla versione 2.7 mostrava questo comportamento. Vedi docs.freebsd.org/info/g++FAQ/g++FAQ.info.for_scope.html
Jeremy

5
@Damon non era quando VS6 è stato rilasciato per la prima volta; tuttavia, quando gli standard sono cambiati, non è mai stato rilasciato un aggiornamento conforme ad essi. VS6 è rimasto popolare per alcuni anni dopo la modifica degli standard.
UKMonkey

7
Attribuire questo a un peccato di un vecchio compilatore Microsoft è falso. Questo comportamento era in realtà una caratteristica delle bozze di standard C ++, e un certo numero di compilatori lo facevano (non solo i compilatori Microsoft). Dalla memoria, è stato modificato in una bozza intorno al 1995 per rendere la variabile locale al ciclo, circa tre anni prima che il primo standard C ++ fosse ratificato. Quindi la maggior parte dei compilatori C ++ precedenti (circa) al 1996 funzionavano in questo modo.
Peter

15

{e }creerà uno scope e se definisci alcune variabili nello scope non puoi accedervi dall'esterno. Ma forcrea già quell'ambito. Così

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

equivale a

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

ma se definisci qualcosa tra di loro, c'è una differenza

{int a = 0; for(int i = 0; i < count; ++i){}}

In questo esempio, anon sarà accessibile dall'esterno dell'ambito.


2

Nel tuo esempio particolare non c'è motivo per loro.

A volte potresti voler creare un ambito per una variabile:

float average;
// ...

{
int sum = 0;
for (int i = 0; i < count; ++i)
{
   sum += v[i];
}
average = (float)sum / count;
}

// use average
// sum not in scope here

Tuttavia vedo questo un anti-pattern. Di solito se hai bisogno di farlo, molto probabilmente fordovrebbe essere la sua funzione.


Va bene se pensi che dovrebbe essere nella sua funzione (posso pensare a molte volte in cui ciò aggiungerebbe solo un sovraccarico per lo meno ma non ci andrò) una domanda ipotetica per te: e se hai bisogno di un ambito locale specifico per un caso di commutazione? Ci sono certamente volte in cui l'aggiunta di un ulteriore ambito (che ovviamente fa anche una funzione) (nota che per il tuo esempio non penso affatto che una funzione separata sia una cattiva idea) non è necessario ma altre volte non è così semplice anche se ci sono altri modi.
Pryftan

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.