«ЕСЛИ» порядок оценки аргумента? - PullRequest
36 голосов
/ 28 октября 2011
if(a && b)
{
  do something;
}

есть ли возможность оценивать аргументы справа налево (b -> a)?

если "да", что влияет на порядок оценки?м с использованием VS2008)

Ответы [ 6 ]

55 голосов
/ 28 октября 2011

В 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.

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

44 голосов
/ 28 октября 2011

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

Если вы хотите, чтобы b оценивался первым:

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

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

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

if ( ra && rb )
{
  //do something
}
7 голосов
/ 28 октября 2011

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

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

4 голосов
/ 27 ноября 2013

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

Прочитайте здесь для более полного объяснения набора правил: оценка заказа

2 голосов
/ 28 октября 2011

Он будет оценивать слева направо и закорачивает оценку, если может (например, если оценка оценивается как ложная, оценка не будет b).

Если вы заботитесь о порядке, в котором они оцениваютсявам просто нужно указать их в желаемом порядке оценки в вашем операторе if.

1 голос
/ 16 февраля 2016

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

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

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

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

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