Почему вы не можете объявить переменную внутри части выражения цикла do while?
следующий синтаксис:
while (int i = get_data())
{
}
но это не так:
do
{
} while (int i = get_data());
мы можем увидеть почему через проект стандарта:
[N4140/6.4]
1
[...]condition: expression attribute-specifier-seqoptdecl-specifier-seq declarator = initializer-clause attribute-specifier-seqoptdecl-specifier-seq declarator braced-init-list
2
правила для условий применяются как к selection-заявления и кfor
иwhile
заявления (6.5). [...]
[N4140/6.5]
1
итерации операторы задают цикл.iteration-statement:while
( condition ) statementdo
statementwhile
( expression ) ;
вместо этого, вы вынуждены делать что-то уродливое, как:
int i = get_data();
do
{
} while ((i = get_data())); // double parentheses sic
каково обоснование этого?
6 ответов
похоже, что определение области будет проблемой, какова будет область i
объявлен в while
часть do while
заявление? Казалось бы, довольно неестественно иметь переменную, доступную в цикле, когда объявление фактически ниже самого цикла. У вас нет этой проблемы с другими циклами, так как объявления приходят перед телом цикла.
если мы посмотрим на проект стандарта C++ мы видим из раздела 6.5.1
в пока заявление, что для в то время как заявление что:
while (T t = x) statement
эквивалентно:
label:
{ // start of condition scope
T t = x;
if (t) {
statement
goto label;
}
} // end of condition scope
и:
переменной в условии уничтожается и создается с каждой итерации цикла.
как бы мы сформулировали это для do while
случае?
и, как указывает cdhowie, если мы посмотрим на раздел 6.5.2
заявление do он говорит (акцент шахта):
в инструкции do подстанция выполняется повторно до тех пор, пока значение выражения становится false. испытание происходит после каждого исполнение заявления.
что означает, что тело цикла оценивается до того, как мы даже достигнем объявления.
хотя мы могли бы создать исключение для этого случая, это нарушило бы наше интуитивное чувство, что в целом точка объявление имени после того, как мы увидим полное объявление (С некоторыми исключениями, например переменными-членами класса) с непонятными преимуществами. пункт декларации рассматривается в разделе 3.3.2
.
есть несколько причин, почему это было бы трудно допустить.
язык придерживается общего правила, что все должно быть объявлено выше точки использования. В этом случае переменная, объявленная в do-while
будет объявлен ниже свой предполагаемый естественный объем (тело цикла). Сделать эту переменную доступной внутри цикла потребовало бы специальной обработки для do-while
циклы. Хотя мы знаем примеры таких специальных обработка (например, тела функций-членов в классе могут видеть все члены класса, включая объявленные ниже), вероятно, нет большого практического смысла делать это для do-while
циклы.
в случае do-while
эти правила специального режима также потребуют поиска значимого способа обработки инициализации переменных, объявленных таким образом. Обратите внимание, что в языке C++ время жизни такой переменной ограничивается одной итерации цикла, т. е. переменная создается и уничтожается на каждой итерации. Это означает, что для do-while
цикл переменная всегда будет оставаться неинициализированной, если вы не введете какое-то правило, которое каким-то образом переместит инициализацию в начало тела цикла. На мой взгляд, это было бы довольно запутанно.
было бы очень неестественно иметь заявление i
после блока, а затем иметь доступ к нему в блоке. Объявление в for
и while
хорошие короткие руки, которые дают ограниченное использование переменной, которая необходима в логике цикла.
чище сделать это таким образом:
int i;
do {
i = get_data();
// whatever you want to do with i;
} while (i != 0);
это потому, что все остальное следует практике объявления переменных перед их использованием, например:
public static void main(String[] args){
// scope of args
}
for(int i=1; i<10; i++){
// scope of i
}
{
...
int somevar;
//begin scope of var
...
//end of scope of var
}
это потому, что вещи анализируются сверху вниз, и потому, что после этого соглашения вещи интуитивно понятны, поэтому вы можете объявить некоторое время(int var
do while не имеет никакого смысла объявлять переменную, потому что область закончится одновременно это будет проверено, потому что именно тогда этот блок будет завершен.
добавить
#define do(cond) switch (cond) do default:
в начале вашего кода.
теперь вы можете написать
do (int i = get_data())
{
// your code
} while ((i = get_data()));
важно, чтобы это #define
не нарушает исходный синтаксис do
ключевое слово в цикле do-while.
однако я признаю, что это неясно.
ваш первый синтаксис действителен, а второй нет. Однако, ваш цикл while будет повторяться вечно, даже если ваша функция get_data() возвращает 0. Не уверен, что это именно то, чего ты хочешь.