Добрый вечер. Пришел с вопросом. Читал тут книгу, в одном фрагменте было написано, что если я укажу тип данных у переменной в условии функции, то значение переменной будет иметь большую область видимости, чем если бы я указал переменную без типа. То есть без типа переменная будет действовать, пока активен цикл, но с типом данных она будет действовать и на еще одни скобки.
Решил проверить. Написал с int'ом-все сработало. Убрал int-и программа стала использовать значение переменной в цикле во всей программе и по какому-то принципу компилятор его даже изменил, по какому-я не понимаю.
Вопрос: Я некорректно понял инфу из учебника? Да, то как все должно быть на самом деле?
#include
int main() {
int done=5;
int howmany=3;
for( done=1; done
7
7
3
Ответ
Рассмотрим следующую программу
#include
int main()
{
int done = 5;
int howmany = 3;
for ( done = 1; done < howmany; done++ )
{
std::cout << done << std::endl;
}
std::cout << done << std::endl;
return 0;
}
Ее вывод на консоль
1
2
3
В этой программе в блоке кода функции main объявлена переменная done. Сначала эта переменная инициализируется значением 5
int done = 5;
а затем в предложении for ей присваивается значение 1
for ( done = 1; done < howmany; done++ )
^^^^^^^^
После выхода из цикла эта переменная будет иметь значение 3.
Теперь рассмотрим следующую программу
#include
int main()
{
int done = 5;
int howmany = 3;
for ( int done = 1; done < howmany; done++ )
{
std::cout << done << std::endl;
}
std::cout << done << std::endl;
return 0;
}
Ее вывод на консоль
1
2
5
В этой программе в предложении for объявляется переменная с именем done, совпадающем с именем переменной, объявленной в блоке кода main.
for ( int done = 1; done < howmany; done++ )
^^^^^^^^^^^^
Эта переменная в предложении for скрывает одноименную переменную с таким же именем, объявленную во внешнем блоке кода. Ее область определения - это тело цикла for. После выхода из цикла данная переменная прекращает свое существование.
Из стандарта C++ (6.5.3 The for statement)
3 If the for-init-statement is a declaration, the scope of the name(s)
declared extends to the end of the for statement.
Поэтому последняя строка вывода программы
5
уже выводит на консоль значение переменной done, которая была объявлена до цикла в блоке кода функции main
В общем случае имя, объявленное во внутренней области объявления скрывает такое же имя, объявленное во внешней области объявления
Из стандарта C++ (3.3.10 Name hiding)
1 A name can be hidden by an explicit declaration of that same name in
a nested declarative region or derived class (10.2).
Обратите внимание, что есть важное отличие в определении предложения for между C++ и C.
В C++ во второй части предложения for, где записывается условие, также может быть объявление.
Рассмотрите следующую демонстрационную программу
#include
int main()
{
int done = 5;
int howmany = 3;
for ( ; int howmany = done; done-- )
{
std::cout << done << std::endl;
}
std::cout << '
' << howmany << std::endl;
return 0;
}
Ее вывод на консоль
5
4
3
2
1
3
При каждой итерации данного цикла for
for ( ; int howmany = done; done-- )
^^^^^^^^^^^^^^^^^^
объявляется переменная howmany, которая скрывает переменную с таким же именем, объявленную в функции main. Значение, присвоенное этой переменной, преобразуется к булевскому типу. Если оно равно 0, то условие будет ложным и произойдет выход из цикла.
После цикла выводится уже значение переменной howmany, объявленной в main
Ну, и напоследок пример, когда в предложении for сразу в двух его частях объявляются переменные, которые скрывают одноименные переменные с теми же именами, объявленные в main. После выхода из цикла эти переменные прекращают свое существование, и становятся видимыми переменные, объявленные в main
#include
int main()
{
int done = 10;
int howmany = 20;
for ( int done = 5; int howmany = done; done-- )
{
std::cout << done << std::endl;
}
std::cout << '
' << done << std::endl;
std::cout << howmany << std::endl;
return 0;
}
Вывод этой программы на консоль
5
4
3
2
1
10
20
Предложение for в этой программе логически может быть представлено как
{
int done = 5;
Label_repeat:
{
int howmany = done;
if ( howmany != 0 )
{
std::cout << done << std::endl;
done--;
goto Label_repeat;
}
else
{
goto Label_exit;
}
}
}
Label_exit:
//...
Комментариев нет:
Отправить комментарий