Рассмотрите следующий код:
#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 ++ жалуется crosses initialization of 'int r'
Вопросы о.My:
crosses initialization
?x + y
передать компиляцию, но позже неудавшийся?crosses initialization
?Править:
Я знаю, что должен использовать скобки для определения объема r
но я хочу знать, почему, например, почему не-POD не мог быть определен в операторе переключения мультислучая.
Спасибо.
Версия с int r = x + y;
также не будет компилироваться.
Проблема в том, что r
может попасть в область действия без выполнения своего инициализатора. Код будет нормально компилироваться, если вы полностью удалите инициализатор (т.е.строка будет читать int r;
).
Лучшее, что вы можете сделать, - это ограничить область видимости переменной. Таким образом вы удовлетворите и компилятор, и читателя.
switch(i)
{
case 1:
{
int r = 1;
cout << r;
}
break;
case 2:
{
int r = x - y;
cout << r;
}
break;
};
Стандарт говорит (6.7 / 3):
Можно выполнить передачу в блок, но не таким образом, чтобы обойти объявления с инициализацией. Программа, которая перескакивает из точки, где локальная переменная с автоматической продолжительностью хранения не находится в области видимости, к точке, где она находится в области видимости, плохо сформирована, если только переменная не имеет тип POD (3.9) и объявлена без инициализатора (8.5).
Вы должны заключить содержимое case
в скобки, чтобы дать ему область видимости, таким образом вы можете объявить внутри него локальные переменные:
switch(i) {
case 1:
{
// int r = x + y; -- OK
int r = 1; // Failed to Compile
cout << r;
}
break;
case 2:
...
break;
};
Можно передать в блок, но не каким-либо образом это обходит объявления с инициализацией. Программа, которая перескакивает из точки, в которой локальная переменная с автоматической продолжительностью хранения не находится в области видимости, к точке, где она находится в области видимости, является некорректной, если только переменная не имеет тип POD и не объявлена без инициализатора.
[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]
Переход от условия оператора switch к метке case считается скачком в этом отношении.
Я предлагаю вам продвигать вашу переменную r
перед оператором switch
. Если вы хотите использовать переменную в блоках case
(или с тем же именем переменной, но разными способами использования), определите ее перед оператором 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;
};
}
Одним из преимуществ является то, что компилятор не имеет для выполнения локального выделения (также известного как отправка в стек) в каждом блоке
.
Недостатком этого подхода является то, что случаи «попадают» в другие случаи (т.е. без использования break
), поскольку переменная будет иметь предыдущее значение.