Каковы признаки инициализации крестов?
рассмотрим следующий код:
#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'
. мои вопросы:
- что это
crosses initialization
? - почему первый инициализатор
x + y
передать компиляцию, но позже не удалось? - каковы проблемы так называемых
crosses initialization
?
EDIT:
Я знаю, что я должен использовать скобки, чтобы указать область r
но я хочу знать, почему, например, почему non-POD не может быть определено в операторе переключателя мульти-случая.
спасибо.
4 ответа:
версия
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; }; }
одним из преимуществ является то, что компилятор не должен выполнять локальное выделение (он же толкает на стек) в каждом элементе
case
заблокировать.недостатком этого подхода является то, что случаи "попадают" в другие случаи (т. е. без использования
break
), так как переменная будет иметь прежнее значение.