В каком порядке оцениваются выражения в состоянии `if`? [Дубликат]

Просто измените функцию:

def notastonishinganymore(a = []): '''The name is just a joke :)'''
    a = a[:]
    a.append(5)
    return a
32
задан winnerrrr 28 October 2011 в 06:26
поделиться

6 ответов

Порядок оценки задается стандартом и left-to-right. Самое левое выражение всегда будет оценено сначала с предложением &&.

Если вы хотите сначала оценить оценку b:

if(b && a)
{
  //do something
}

Если оба аргумента являются методами и вы хотите, чтобы оба они оценивались независимо от их результата:

bool rb = b();
bool ra = a();

if ( ra && rb )
{
  //do something
}
38
ответ дан Luchian Grigore 22 August 2018 в 00:11
поделиться
  • 1
    это облегчение ... на этот раз c ++ имеет правильное поведение по умолчанию, а не удивительно непонятное – Aviad Rozenhek 30 January 2013 в 19:57
  • 2
    @AviadRozenhek: вы правы, чтобы испугаться, потому что действительно возможно, что выражение b оценивается перед выражением a. Для этого, однако, оператор не должен быть предопределенным && логическим и оператором, а перегрузкой для пользовательских типов. В этом случае порядок оценки аргументов неуточнен (и хуже того, что вы даже не можете ожидать реального упорядочения, потому что оценка может даже быть «смешанной»: бит a, затем некоторые из b, затем больше a, затем снова останутся некоторые оставшиеся биты b и, наконец, пользовательский оператор). – 6502 18 February 2014 в 23:13
  • 3
    В чем дело, если вместо этого используется ||? Он должен оставаться тем же, если некоторые оптимизаторы компилятора не gunk it iu, правильно ли @ 6502? – mdw7326 13 November 2014 в 20:48
  • 4
    @ mdw7326 || также является короткозамкнутым - если первое условие истинно, второе не будет оцениваться. Это не оптимизация компилятора, это требуется стандартом. – Luchian Grigore 13 November 2014 в 20:49
  • 5
    @LuchianGrigore. Я понимаю, что, наверное, я не очень точно изложил свой вопрос. С помощью оператора || выражения вычисляются в порядке (слева направо) до тех пор, пока все выражения не будут оценены или , пока не будет найдено выражение true, правильно? – mdw7326 13 November 2014 в 20:52

С C ++ существует только несколько операторов, которые гарантируют порядок оценки

  • operator && сначала оценивает левый операнд, и если значение логически false, то оно позволяет избежать оценки правильного операнда. Типичным использованием является, например, if (x > 0 && k/x < limit) ..., который позволяет избежать деления на нулевые проблемы.
  • operator || сначала оценивает левый операнд, и если значение логически true, то оно позволяет избежать оценки правильного операнда. Например, if (overwrite_files || confirm("File existing, overwrite?")) ... не будет запрашивать подтверждение, когда установлен флаг overwrite_files.
  • operator , оценивает сначала левый операнд, а затем правый операнд, возвращая значение правого операнда. Этот оператор не используется очень часто. Обратите внимание, что запятые между параметрами в вызове функции не являются операторами запятой, и порядок оценки не гарантируется.
  • Тройной оператор x?y:z сначала оценивает x, а затем в зависимости от логического значения результат оценивает либо только y, либо только z.

Для всех других операторов порядок оценки не указан.

Ситуация на самом деле хуже, потому что это не то, что порядок не указан, но что для выражения вообще нет даже «порядка», и, например, в

std::cout << f() << g() << x(k(), h());

возможно, что функции будут вызываться в порядке h-g-k-x-f (это немного тревожно, потому что ментальная модель оператора << каким-то образом передает идею последовательности, но на самом деле уважает последовательность только в результатах порядка, которые помещаются в поток, а не в том порядке, в котором результаты вычисляются).

Очевидно, что зависимостей значений в выражении могут вводить некоторую гарантию порядка; например, в приведенном выше выражении гарантировано, что оба k() и h() будут вызываться до x(...), потому что для вызова x необходимы обратные значения из обоих.

Обратите также внимание на то, что гарантии для &&, || и , действительны только для предопределенных операторов. Если вы перегружаете эти операторы для своих типов, они будут в этом случае, как обычные вызовы функций, и порядок оценки операндов будет неуказан.

48
ответ дан 6502 22 August 2018 в 00:11
поделиться
  • 1
    Просто nit, но зависимости значений также налагают порядок. В выражении, подобном (a + b) * c, a и b должны быть оценены перед добавлением, и добавление должно происходить перед умножением. Как правило, этот эффект невозможен, но если операторы перегружены, он может быть виден. – James Kanze 28 October 2011 в 09:07
  • 2
    @JamesKanze: Хорошо. Я думаю, что это похоже на такой язык, как C ++, но добавляет в любом случае примечание. – 6502 28 October 2011 в 09:31
2
ответ дан Dylan Smith 22 August 2018 в 00:11
поделиться

В этом случае, поскольку вы используете &&, a всегда будет оцениваться первым, потому что результат используется для определения того, следует ли коротко замыкать выражение.

Если a возвращает false, тогда b вообще не разрешается оценивать.

7
ответ дан flak37 22 August 2018 в 00:11
поделиться

Встроенный оператор && всегда сначала оценивает свой левый операнд. Например:

if (a && b)
{
   //block of code
}

Если a - false, тогда b не будет оцениваться.

Если вы хотите сначала оценить оценку b и a, только если b истинно, просто напишите выражение по-другому:

if (b && a)
{
   //block of code
}
1
ответ дан GreatBigBore 22 August 2018 в 00:11
поделиться

Каждое вычисление значения и побочный эффект первого (левого) аргумента встроенного логического оператора AND & amp; & amp; & amp; и встроенный логический оператор OR || секвентируется перед каждым вычислением значения и побочным эффектом второго (правого) аргумента.

Читайте здесь для более полного объяснения установленных правил: оценка порядка

3
ответ дан Pacheco 22 August 2018 в 00:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: