Оценка короткого замыкания C++

Может быть, я упускаю что-то довольно простое, но у меня происходит сбой, когда я разыменовываю указатель, даже если я проверяю точку в самом начале выражения.

if( var1 &&
    bool1 || bool2 &&
    var1->DoSomething() )
{

}

var1 является нулевым указателем, но Var1->Dosomething() все еще вызывается. Насколько я понимаю, && и || Оператор в C++ является коротким замыканием, поэтому, если бы var1 был нулевым, он просто завершился бы в самом начале. Или есть что-то еще, что мне не хватает?


person user1149438    schedule 14.01.2012    source источник
comment
Если сомневаетесь, в скобках!   -  person Cody Gray    schedule 14.01.2012


Ответы (3)


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

(var1 && bool1) || (bool2 && var1->DoSomething() )

Таким образом, поскольку var1 оценивается как false, bool1 не оценивается, а (var1 && bool1) дает false, поэтому (bool2 && var1->DoSomething()) необходимо оценивать. И если bool2 окажется истинным, то var1->DoSomething() также будет оцениваться, что приведет к неопределенному поведению.

Просто добавьте несколько круглых скобок (для конкретного дерева выражений, которое вам нужно), и все будет в порядке.

person Armen Tsirunyan    schedule 14.01.2012

Поскольку && имеет более высокий приоритет, чем ||, ваше выражение анализируется как (var1 && bool1) || (bool2 && var1->DoSomething()). Теперь, поскольку var1 является нулевым указателем, оценка короткого замыкания означает, что bool1 не оценивается, а левая часть || оценивается как ложная. Таким образом, чтобы узнать значение выражения, необходимо вычислить правую часть (т. е. краткое вычисление здесь не работает!). Правая часть || равна bool2 && var1->DoSomething(), поэтому, если bool2 истинно, будет оцениваться var1->DoSomething(). Заметьте также, что даже для var1, отличного от null, результат eexpression не всегда будет таким, как вы, вероятно, ожидали.

person celtschk    schedule 14.01.2012

Простой. && имеет более высокий приоритет, поэтому ваше выражение выглядит следующим образом:

if( ( var1 && bool1 ) || ( bool2 && var1->DoSomething()) )

пытаться

if( var1 && ( bool1 || bool2 ) && var1->DoSomething() )

в противном случае первое выражение car1 && bool1 терпит неудачу, и вычисляется второе выражение. поскольку bool2 возвращает true, очевидно, ваш указатель разыменовывается, если bool2 имеет значение true.

посмотрите здесь список приоритетов: http://en.cppreference.com/w/cpp/language/operator_precedence или используйте Google.

person ted    schedule 14.01.2012