2015-01-19 3 views
0

В C++, если я напишу следующий оператор if. Какова потенциальная проблема? Является ли поведение четко определенным? Благодарю.C++ if (func1() && func2()), требуется ли func1 перед func2?

int i = 0; 
// func1 will return the updated value for i. 
// func2 will use the new value of i. 
if (func1(i) && func2(i)) { ...} 

Или, вероятно, & & может быть изменен на ||, это вызов все еще по-прежнему хорошо?

+0

Если 'func2' должно использовать новое значение для' i', тогда 'func1' должен принимать входной параметр int-reference (' int & '). – Jonas

ответ

2

Да, кроме правила as-if.

func1() && func2() означает if (func1()) return true; else return func2()!=false; приблизительно (return здесь не настоящий «возврат», и это все одно выражение, поэтому только грубо). func1()?true:func2() ближе к тому, что это означает.

C++ имеет правила короткого замыкания. && сначала оценивает левую сторону, затем, если он возвращает false, тогда он оценивает правую сторону.

Но всегда есть исключения.

Если кто-то переопределил && для двух аргументов, обе стороны будут оценены до передачи &&. Это хорошая причина не переопределять &&.

Во-вторых, как если бы правило означает, что компилятор волен оценивать func2(), если это было бы так, если вы не сделали этого, когда func1() вернулся true, и если когда func1() возвращается false он ведет себя так же как- если он был назван вторым. То есть, если нет способа, чтобы вызов func2() мог быть «замечен», до неопределенного поведения.

Примером такого рода может быть строгий псевдоним, где func1() изменяет некоторое значение, для которого нет определенного способа поведения для func2() для его обнаружения. Но ожидается, что func2() через неопределенное поведение (скажем, нарушение строгой псевдонимы) обнаружит изменение.

Если func2() не имеет никакого другого взаимодействия с func1() доказуема, и без каких-либо побочных эффектов, то func2() может быть оценен до или после func1() под как если бы правилом оптимизации. Это может быть полезно, потому что современные процессоры могут выполнять несколько операций одновременно (даже в одном «потоке» исполнения).

Если бы он на самом деле были оценены после, результат func2() могло быть иначе, а потому, что зависимость зависит от неопределенного поведения компилятор разрешается путешествия во времени и не имеют результата вы ожидаете быть произведены.

Долгий и недостаток в том, что понимание C++, как будто это портативная сборка, недостаточна. Поэтому, пока func1() должен быть вызван до func2() логически в абстрактной машине, на которой работает C++, это не значит, что это нужно делать на аппаратном обеспечении, которое ваша программа действительно компилирует.

2

func1 будет возвращен до func2. func2 не будет вызываться, если func1 возвращает false.

В случае ||, func2 не будет вызываться, если func1 возвращает true. Это называется короткозамкнутым.

6

Да, первый операнд && и || всегда оценивается первым.

Второй операнд оценивается только в том случае, если это необходимо, в соответствии со значением первого; это иногда называют short-circuiting. Для && это называется только, если первое верно; для ||, только если первое значение false.