Рассмотрим следующий код:
#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
?
Я знаю, что должен использовать скобки, чтобы указать объем r
, но я хочу знать, почему, например, почему не-POD нельзя определить в операторе переключения с несколькими регистрами.
c++
initialization
Jichao
источник
источник
Ответы:
Версия с
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):
источник
int r = x + y
.Вы должны поместить содержимое
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
), поскольку переменная будет иметь предыдущее значение.источник