Подтвердить что ты не робот

Почему вы не можете объявить переменную внутри части выражения цикла while?

Следующий синтаксис действителен:

while (int i = get_data())
{
}

Но следующее не так:

do
{
} while (int i = get_data());

Мы можем видеть, почему через проект стандарта N4140 раздел 6.4:

1 [...]

condition:
     expression
     attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
     attribute-specifier-seqopt decl-specifier-seq declarator braced-init-list

2 Правила для условий применяются как к операторам выбора, так и к операторам for и while (6.5). [...]

и раздел 6.5

1 Итерационные операторы определяют цикл.

      iteration-statement: 
             while ( condition ) statement
             do statement while ( expression ) ;

Вместо этого вы вынуждены делать что-то ужасное:

int i = get_data();
do
{
} while ((i = get_data())); // double parentheses sic

Что является обоснованием для этого?

4b9b3361

Ответ 1

Кажется, проблема в том, чтобы ограничить область применения, какова будет область действия, которую i объявил в части while находящейся в выражении do while? Казалось бы, довольно неестественно иметь переменную, доступную в цикле, когда объявление фактически находится ниже самого цикла. У вас нет этой проблемы с другими циклами, так как объявления предшествуют телу цикла.

Если мы посмотрим на черновик стандартного раздела C++ [stmt. while] p2, то увидим, что для оператора while:

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, если мы посмотрим на раздел [stmt.do] p2, он говорит (выделение мое):

В операторе do подстановка выполняется несколько раз, пока значение выражения не станет ложным. Тест проводится после каждого выполнения оператора.

что означает, что тело цикла вычисляется еще до того, как мы достигнем объявления.

Хотя мы могли бы создать исключение для этого случая, это нарушило бы наше интуитивное чувство, что в общем случае точка объявления имени находится после того, как мы видим полное объявление (за некоторыми исключениями, например, для переменных членов класса) с неясными преимуществами. Точка декларации описана в разделе 3.3.2.

Ответ 2

Есть несколько причин, почему это было бы трудно разрешить.

Язык придерживается общего правила, согласно которому все должно быть объявлено выше точки использования. В этом случае переменная, объявленная в do-while, будет объявлена ​​ниже ожидаемой естественной области (тела цикла). Обеспечение доступности этой переменной внутри цикла потребовало бы специальной обработки циклов do-while. Несмотря на то, что мы знаем примеры такого специального лечения (например, в классах членов-членов класса можно увидеть всех членов класса, включая те, которые указаны ниже), вероятно, не так много практического смысла при выполнении циклов do-while.

В случае do-while эти специальные правила обработки также потребуют поиска значимого способа обработки инициализации переменных, объявленных таким образом. Обратите внимание, что на языке С++ время жизни такой переменной ограничено одной итерацией цикла, т.е. Переменная создается и уничтожается на каждой итерации. Это означает, что для цикла do-while переменная всегда останется неинициализированной, если вы не введете какое-то правило, которое каким-то образом перенесет инициализацию в начало тела цикла. По моему мнению, это будет довольно сложно.

Ответ 3

Было бы очень неестественно иметь объявление i после блока и затем иметь доступ к нему в блоке. Декларация в for и while - это хорошие короткие руки, которые используют ограниченную область видимости для переменной, которая необходима в логике цикла.

Очиститель, чтобы сделать это следующим образом:

int i;
do {
  i = get_data();
  // whatever you want to do with i;
} while (i != 0);

Ответ 4

Это потому, что все остальное следует за практикой объявления переменных перед их использованием, например:

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 < 10), поскольку область этого var будет областью внутри цикла, после декларация.

Делать пока не имеет смысла объявлять переменную, потому что область действия будет заканчиваться, в то же время она будет проверяться, потому что когда завершается этот блок.

Ответ 5

Добавьте это

#define do(cond) switch (cond) do default:

в начале вашего кода.

Теперь вы можете написать

do (int i = get_data()) 
{

    // your code

} while ((i = get_data()));

Важно, чтобы этот #define не нарушал исходный синтаксис ключевого слова do в цикле do-while.

Однако, я признаю, что это неясно.

Ответ 6

Ваш первый синтаксис действителен, а второй - нет. Тем не менее, ваш цикл while будет работать навсегда, даже если ваша функция get_data() возвращает 0. Не уверен, что это именно то, что вы хотите.