87 votes

Quels sont les signes d'initialisation des croisements?

Envisager de code suivant:

#include <iostream>
using namespace std;

int main()
{
    int x, y, i;
    cin >> x >> y >> i;
    switch(i) {
        case 1:
            // int r = x + y; -- OK
            int r = 1; // Failed to Compile
            cout << r;
            break;
        case 2:
            r = x - y;
            cout << r;
            break;
    };
}

G++ se plaint crosses initialization of 'int r'.Mes questions sont les suivantes:

  1. Qu'est - crosses initialization?
  2. Pourquoi le premier initialiseur x + y passer à la compilation,mais le plus tard échoué?
  3. Quels sont les problèmes de la soi-disant crosses initialization?

EDIT:
Je sais que je devrais utiliser des parenthèses pour préciser le champ de l' r , mais je veux savoir pourquoi,par exemple, pourquoi les non-POD n'a pas pu être défini en multi-cas de l'instruction switch.

Merci.

103voto

avakar Points 20031

La version avec int r = x + y; ne compile pas.

Le problème est qu'il est possible pour l' r pour venir à portée sans son initialiseur en cours d'exécution. Le code compile bien si vous avez supprimé l'initialiseur complètement (c'est à dire la ligne lisez int r;).

La meilleure chose que vous pouvez faire est de limiter la portée de la variable. De cette façon, vous pourrez satisfaire à la fois le compilateur et le lecteur.

switch(i)
{
case 1:
    {
        int r = 1;
        cout << r;
    }
    break;
case 2:
    {
        int r = x - y;
        cout << r;
    }
    break;
};

Que dit la Norme (6.7/3):

Il est possible de transférer en un bloc, mais pas d'une manière qui contourne les déclarations à l'initialisation. Un programme de sauts à partir d'un point où une variable locale automatique de la durée de stockage n'est pas portée à un point où il est dans la portée est mal formé, à moins que la variable est de type POD (3.9) et est déclarée sans un initialiseur (8.5).

37voto

Péter Török Points 72981

Vous devez mettre le contenu du case entre parenthèses pour lui donner la portée, de cette façon vous pouvez déclarer des variables locales à l'intérieur:

 switch(i) {
    case 1:
        {
            // int r = x + y; -- OK
            int r = 1; // Failed to Compile
            cout << r;
        }
        break;
    case 2:
        ...
        break;
};
 

3voto

Ashish Yadav Points 718

Il est possible de transférer dans un bloc, mais pas de manière à contourner les déclarations avec initialisation. Un programme qui saute d'un point où une variable locale avec une durée de stockage automatique n'est pas dans la portée à un point où elle est dans la portée est mal formé, sauf si la variable a le type POD et est déclarée sans initialiseur.

 [Example: Code:

void f()
{
  // ...
  goto lx;    // ill-formed: jump into scope of `a'
  // ...
 ly:
    X a = 1;
  // ...
 lx:
   goto ly;    // ok, jump implies destructor
 // call for `a' followed by construction
 // again immediately following label ly
}

--end example]
 

Le transfert de la condition d'une instruction switch à une étiquette de cas est considéré comme un saut à cet égard.

0voto

Thomas Matthews Points 19838

Je vous suggère de faire la promotion de votre r variable avant de l' switch déclaration. Si vous souhaitez utiliser une variable dans l' case blocs, (ou le même nom de variable, mais de différents usages), de la définir avant l'instruction switch:

#include <iostream>
using namespace std;

int main()
{
    int x, y, i;
    cin >> x >> y >> i;
// Define the variable before the switch.
    int r;
    switch(i) {
        case 1:
            r = x + y
            cout << r;
            break;
        case 2:
            r = x - y;
            cout << r;
            break;
    };
}

L'un des avantages est que le compilateur n'a pas à effectuer allocation locale (un.k.un. en poussant sur la pile) dans chaque case bloc.

Un inconvénient de cette approche est lorsque des cas de "tomber" dans les autres cas (c'est à dire sans l'aide d' break), la variable aura une valeur précédente.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X