Für Schlaufe in eigenen geschweiften Klammern

117

Ich bin auf dieses For-Loop-Layout gestoßen:

#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;
}

Ich habe mich gefragt, wozu diese zusätzliche Schicht von Zahnspangen gut ist. Dies erscheint einige Male in unserer Codebasis.

Ed Norman
quelle
47
Sie sind völlig überflüssig in dem Code-Snippet, das Sie gepostet haben
EdChum
25
Welche Compiler wurden mit diesem Code verwendet? Wurde VS 6 speziell verwendet?
UKMonkey
5
@ EdNorman jetzt mit Ihrer Bearbeitung ist es viel klarer. Es scheint, dass die richtige Antwort die von UKMonkey ist. Mit dem modernen C ++ - Compiler können Sie die geschweiften Klammern einfach ablegen.
Jabberwocky
8
Alternativ könnte es sich um generierten Code handeln (seufzte jemand, der sich gerade mit Rhapsody auseinandersetzt)
Mawg sagt, Monica am
4
Ein möglicher Grund ist, wenn der Code einmal OpenMP-Parallelanweisungen hatte (oder in Zukunft haben soll).
Jamesqf

Antworten:

286

Es war einmal, vor vielen Monden, VS6 existierte und war beliebt. Es entsprach jedoch nicht einer Reihe von C ++ - Standards. Dies war zu dem Zeitpunkt angemessen, als der Standard kurz vor (im selben Jahr) offiziell veröffentlicht wurde. Soweit mir bekannt ist, hat es sich jedoch an den Entwurf des Standards gehalten.

Einer der Standards, die sich zwischen dem Entwurf und dem offiziellen Standard geändert haben, war die Lebensdauer der im ersten Abschnitt erstellten for-Schleifenvariablen. Dies führt dazu, dass der folgende Code nicht kompiliert werden kann

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

weil iwurde von der Sekunde für Schleife neu definiert.

Während andere Compiler ebenfalls unter diesem Fehler litten; Ich hebe das VS6 hervor, da es nach der Veröffentlichung des Standards einige Jahre lang die einzige Version von Visual Studio blieb, aber nie ein Update für dieses spezielle Problem veröffentlicht hat. was bedeutet, dass es einen größeren Einfluss hatte.

Eine Lösung hierfür besteht darin, die gesamte for-Schleife in einen eigenen Bereich zu zwingen, wie Sie gezeigt haben.

UKMonkey
quelle
49
Sie müssen VS6 nicht finden, um @bolov zu sehen. Setzen Sie "Force Conformance in For Loop Scope" in VS2015 auf "No" und genießen Sie ;-)
alain
5
@alain "Option 'Zc: forScope-' ist veraltet und wird in einer zukünftigen Version entfernt" und kompiliert ohne Probleme ... Ich bin traurig
Bolov
7
GCC vor Version 2.7 zeigte ebenfalls dieses Verhalten. Siehe docs.freebsd.org/info/g++FAQ/g++FAQ.info.for_scope.html
Jeremy
5
@Damon war es nicht, als VS6 zum ersten Mal veröffentlicht wurde; Als sich die Standards änderten, wurde jedoch nie ein Update veröffentlicht, das diesen Standards entsprach. VS6 blieb einige Jahre nach der Änderung der Standards beliebt.
UKMonkey
7
Dies einer Sünde eines alten Microsoft-Compilers zuzuschreiben, ist falsch. Dieses Verhalten war tatsächlich ein Merkmal von C ++ - Standardentwürfen, und eine Reihe von Compilern haben dies getan (nicht nur Microsoft-Compiler). Aus dem Speicher heraus wurde es in einem Entwurf ungefähr 1995 geändert, um die Variable lokal für die Schleife zu machen - ungefähr drei Jahre bevor der erste C ++ - Standard ratifiziert wurde. Die meisten C ++ - Compiler vor (ungefähr) 1996 arbeiteten auf diese Weise.
Peter
15

{und }erstellt einen Bereich. Wenn Sie einige Variablen im Bereich definieren, können Sie von außen nicht darauf zugreifen. Aber forschaffen Sie diesen Bereich bereits. So

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

ist das gleiche wie

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

Aber wenn Sie etwas zwischen ihnen definieren, gibt es einen Unterschied

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

In diesem Beispiel ist ader Zugriff von außerhalb nicht möglich.

cokceken
quelle
2

In Ihrem speziellen Beispiel gibt es keinen Grund dafür.

Manchmal möchten Sie möglicherweise einen Bereich für eine Variable erstellen:

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

Ich sehe dies jedoch als Anti-Muster. Wenn Sie dies benötigen, sollte dies normalerweise foreine eigene Funktion sein.

Bolov
quelle
Okay, wenn Sie denken, dass es in seiner eigenen Funktion sein sollte (ich kann mir viele Male vorstellen, wo dies zumindest nur zusätzlichen Aufwand bedeuten würde, aber ich werde nicht dorthin gehen), eine hypothetische Frage für Sie: Was ist, wenn Sie eine benötigen? spezifischer lokaler Bereich für einen Switch-Fall? Es gibt sicherlich Zeiten, in denen das Hinzufügen eines zusätzlichen Bereichs (was natürlich auch eine Funktion tut) (beachten Sie, dass ich für Ihr Beispiel eine separate Funktion überhaupt nicht für eine schlechte Idee halte) unnötig ist, aber manchmal ist es nicht so einfach, selbst wenn Es gibt andere Möglichkeiten.
Pryftan
2

Es ist ein Blockumfang, der durch {}geschweifte Klammern gekennzeichnet ist. Es wird normalerweise verwendet, um den Bereich der automatischen Speicherung zu markieren . In Ihrem Fall scheint es nichts zu tun, da die for-Schleife in Standard-C ++ einen eigenen Bereich hat.

Ron
quelle