С++ переопределение переменной счетчика циклов непоследовательное поведение?
Я делаю С++ в Visual Studio 2010 и обнаружил нечетное поведение. Короче говоря, я обнаружил, что это не скомпилируется:
for (int i = 0; i < 10; i++)
{
int i = 11;
}
Это кажется правильным, поскольку переменная я уже объявлена в заголовке цикла цикла.
Теперь, однако, если я вставляю другой цикл for перед повторным объявлением i, то внезапно компилятор, intellisense и т.д. код корректен - не дает никаких реальных предупреждений (Tried warnings level 3 и four (/W3 и /w 4)). Таким образом, это будет скомпилировано и запущено:
for (int i = 0; i < 10; i++)
{
for(int j = 0; j < 5; j++)
{
}
int i = 11;
}
Лично мне кажется странным, что включение другого цикла for-loop оправдывает аналогичный сценарий кода.
Любой добрый дух способен рассказать мне, что я здесь не замечаю?
Спасибо заранее!
EDIT:
Вау, спасибо всем за все ответы и демонстрации - Ты потрясающий!:)
Этот образец, разоблачающий ошибку, перешел мне в голову, я просто предположил, что MS уже заметила бы такую вещь и зафиксировала ее... по крайней мере, в VS2013.
Попробовал изменить настройки оптимизации, как было предложено, но это не имело никакого значения.
Спасибо всем!
Первая часть кода
Второй фрагмент кода
Кредит для демонстраций: @Mark Garcia
Ответы
Ответ 1
В соответствии со стандартной спецификацией:
1... имена, объявленные в for-init-statement, находятся в той же декларативной области, что и объявленные в условии
3 Если for-init-statement является объявлением, область имени (имен) объявляется до конца for-statement. [§6.5.3]
и
4Имена, объявленные в for-init-statement, for-range-declaration и в условии if, while, for и switch, являются локальными для оператора if, while, for или switch (включая управляемый оператор), и не должны быть переоформлены в последующем условии этого утверждения или в самом внешнем блоке (или для оператора if любого из самых отдаленных блоков) контролируемого оператора [§3.3.3]
Поведение MSVС++ 2010 не является стандартным и это ошибка.
Ответ 2
когда вы делаете что-то вроде:
for (int i = 0; i < 10; i++)
{
//some code
}
вы объявляете переменную я и ограничиваете ее область видимости для кода. Так что это будет видно только внутри цикла for.
Имея это в виду, ваш первый фрагмент кода переопределяет переменную i;
for (int i = 0; i < 10; i++)
{
int i;
}
компилятор жалуется на переопределение, потому что теперь у вас есть 2 переменные с тем же именем, один и тот же тип данных и одна и та же область.
Что касается того, почему вторая часть кода компилирует ошибку-компилятора. Это зависит исключительно от реализации компилятора; если вы измените уровень оптимизации, он может больше не отображаться.