2010-09-21 19 views
5

In den switch-case-Anweisungen Erklärung-with-Initialisierung ungültig ist aber Erklärung-und-dann-Zuordnung erlaubt ist. Wie im folgenden Codeausschnitt gezeigt.Schalter-Gehäuse: Deklaration-with-Initialisierung und Deklaration-und-dann-Zuordnung

Was ist der Unterschied zwischen diesen beiden Arten von Initialisierungen von der Compiler-Seite? Und warum ist der erste Initialisierungstyp ungültig und der zweite Typ ein gültiger?

switch(val) 
{ 
case 0: 
    int newVal = 42; //Invalid 
    break; 
case 1: 
    int newVal2;  //Valid 
    newVal2 = 42; 
    break; 
case 2: 
    break; 
} 
+0

Welchen Compiler benutzen Sie? – NullUserException

+0

Visual Studio 2008 –

Antwort

4

In der Tat sind beide legal C++. Sie können eine Variable in einem Schaltergehäuse erklären, es sei denn es scoped ist:

switch(val) 
{ 
case 0: 
    { 
    int newVal = 42; // now valid 
    } 
    break; 
case 1: 
    { 
    int newVal2;  // still Valid 
    newVal2 = 42; 
    } 
    break; 
case 2: 
    break; 
} 

Die Tatsache, dass Ihr Compiler ermöglicht Fall 1 ist ein Defekt des Compilers oder möglicherweise eine Erweiterung. Zumindest nach dem Standard.

+0

Die Deklaration von 'int newVal2;' ist gültig, da kein Initialisierer vorhanden ist. –

9

Effektiv ist die Regel, dass Sie nicht in einen Block nach einer Deklaration springen können, die eine Initialisierung (oder nach der Deklaration einer Nicht-POD-Typ-Variable) hat. Der C++ - Standard sagt (C++ 03 §6.7):

Es ist möglich, in einen Block zu übertragen, aber nicht in einer Weise, die Deklarationen mit Initialisierung umgeht. Ein Programm, das (77) von einem Punkt springt, an dem eine lokale Variable mit automatischer Speicherdauer nicht in einem Bereich liegt, in dem sie sich im Geltungsbereich befindet, ist ungültig, es sei denn, die Variable hat den POD-Typ (3.9) und wird ohne deklariert Initialisierer (8.5).

(*) Die Übertragung vom Zustand einer switch Anweisung zu einem case Etikett wird in dieser Hinsicht als ein Sprung angesehen.

int newVal = 42; ist eine Erklärung, die einen Initialisierer (der Teil = 42) aufweist. Das Programm ist schlecht gebildet, denn wenn val1 oder 2 ist, werden Sie nach der Initialisierung in den Switch-Block springen.

int newVal2; ist auch eine Erklärung; Da int ein POD-Typ ist und die Deklaration keinen Initialisierer hat, können Sie über diese Deklaration springen.

+0

+1: Ich suchte nach diesem aber konnte nicht in der Standard – Chubsdad

+0

OK finden. Es ist so, weil der C++ Standard dies sagt. Aber was ist hinter demselben vernünftig? Warum sagt der Standard das? Ist es nicht seltsam, dass int newVal = 42; ist nicht erlaubt wo als int newVal; neuVal = 42; ist erlaubt? –

+0

@Dahiya: Es ist nicht so seltsam; Initialisierung und Zuweisung sind verschiedene Dinge (sie sind für die meisten Nicht-POD-Typen sehr unterschiedliche Dinge, da Konstruktoren an der Initialisierung beteiligt sind). Betrachten Sie zum Beispiel, wenn Sie eine 'std :: string' haben; Wenn Sie über seine Deklaration springen, ist die Variable zugänglich, aber ihr Inhalt ist nicht initialisiert, weil ihr Konstruktor nie aufgerufen wurde. –