16 ответов:
Я еще не видел правильного ответа (и уже есть некоторые) предостережение: Наваз указал на определенную пользователем ловушку. И я сожалею о своем поспешно брошенном upvote на "самый глупый вопрос", потому что кажется, что многие не поняли его правильно, и это дает место для приятного обсуждения оптимизации компилятора :)
ответ:
что это
flag'S тип?в случае
flagна самом деле это пользовательский тип. Тогда это зависит от того, какая перегрузкаoperator==выбран. Конечно, может показаться глупым, что они не будут симметричными, но это, безусловно, разрешено, и я уже видел другие злоупотребления.если
flagявляется встроенным, то оба должны принимать одинаковую скорость.С статья в Википедии on
x86, Я бы поставил наJxxинструкцияifзаявление: возможно aJNZ(перейти, если не ноль) или какой-то эквивалент.Я сомневаюсь компилятор пропускает такую очевидную оптимизацию, даже с отключенными оптимизациями. Это тип вещей, для которых Оптимизация Глазок предназначен для.
EDIT: снова вскочил, так что давайте добавим некоторую сборку (LLVM 2.7 IR)
int regular(int c) { if (c == 0) { return 0; } return 1; } int yoda(int c) { if (0 == c) { return 0; } return 1; } define i32 @regular(i32 %c) nounwind readnone { entry: %not. = icmp ne i32 %c, 0 ; <i1> [#uses=1] %.0 = zext i1 %not. to i32 ; <i32> [#uses=1] ret i32 %.0 } define i32 @yoda(i32 %c) nounwind readnone { entry: %not. = icmp ne i32 %c, 0 ; <i1> [#uses=1] %.0 = zext i1 %not. to i32 ; <i32> [#uses=1] ret i32 %.0 }даже если вы не знаете, как читать ИК, я думаю, что это самоочевидно.
тот же код для amd64 с GCC 4.1.2:
.loc 1 4 0 # int f = argc; movl -20(%rbp), %eax movl %eax, -4(%rbp) .loc 1 6 0 # if( f == 0 ) { cmpl , -4(%rbp) jne .L2 .loc 1 7 0 # return 0; movl , -36(%rbp) jmp .L4 .loc 1 8 0 # } .L2: .loc 1 10 0 # if( 0 == f ) { cmpl , -4(%rbp) jne .L5 .loc 1 11 0 # return 1; movl , -36(%rbp) jmp .L4 .loc 1 12 0 # } .L5: .loc 1 14 0 # return 2; movl , -36(%rbp) .L4: movl -36(%rbp), %eax .loc 1 15 0 # } leave ret
не будет никакой разницы в вашей версии.
Я предполагаю, что
typeфлаг не является определяемым пользователем типом, скорее это какой-то встроенный тип. перечисление является исключением!. Вы можете относиться к перечислению, как будто оно встроено. На самом деле, это ' значения являются одним из встроенных типов!в случае, если это пользовательский тип (кроме
enum), то ответ полностью зависит от того, как ты перегружен оператор==. Обратите внимание, что вы должны перегрузить==определив две функции, по одной для каждой из ваших версий!
нет абсолютно никакой разницы.
вы можете получить очки, отвечая на этот вопрос интервью, ссылаясь на устранение опечаток назначения / сравнения, хотя:
if (flag = 0) // typo here { // code never executes } if (0 = flag) // typo and syntactic error -> compiler complains { // ... }хотя это правда, что, например, C-компилятор предупреждает в случае первого (
flag = 0), нет таких предупреждений в PHP, Perl или Javascript или<insert language here>.
Ну есть разница, когда флаг является определяемым пользователем типом
struct sInt { sInt( int i ) : wrappedInt(i) { std::cout << "ctor called" << std::endl; } operator int() { std::cout << "operator int()" << std::endl; return wrappedInt; } bool operator==(int nComp) { std::cout << "bool operator==(int nComp)" << std::endl; return (nComp == wrappedInt); } int wrappedInt; }; int _tmain(int argc, _TCHAR* argv[]) { sInt s(0); //in this case this will probably be faster if ( 0 == s ) { std::cout << "equal" << std::endl; } if ( s == 0 ) { std::cout << "equal" << std::endl; } }в первом случае (0==s) вызывается оператор преобразования, а затем возвращаемый результат сравнивается с 0. Во втором случае вызывается оператор==.
они должны быть точно такими же с точки зрения скорости.
обратите внимание, однако, что некоторые люди используют, чтобы поставить константу слева в сравнениях равенства (так называемые "условия Йоды"), чтобы избежать всех ошибок, которые могут возникнуть, если вы пишете
=(оператор присваивания) вместо==(оператор сравнения равенства); поскольку присвоение литералу вызывает ошибку компиляции, такого рода ошибки можно избежать.if(flag=0) // <--- typo: = instead of ==; flag is now set to 0 { // this is never executed } if(0=flag) // <--- compiler error, cannot assign value to literal { }С другой стороны, большинство людей найти "Условные обозначения Yoda" странно выглядят и раздражают, тем более что класс ошибок, которые они предотвращают, можно обнаружить также с помощью адекватных предупреждений компилятора.
if(flag=0) // <--- warning: assignment in conditional expression { }
как говорили другие, нет никакой разницы.
0должен быть оценен.flagдолжен быть оценен. Этот процесс занимает одно и то же время, независимо от того, с какой стороны они размещены.правильный ответ будет такой: они оба с одинаковой скоростью.
даже выражения
if(flag==0)иif(0==flag)имеют одинаковое количество символов! Если бы один из них был написан какif(flag== 0), то компилятор будет иметь одно дополнительное пространство для разбора, так что у вас будет законный причина в указании времени компиляции.но так как нет такой вещи, нет абсолютно никакой причины, почему один должен быть быстрее, чем другой. Если есть причина, то компилятор делает некоторые очень, очень странные вещи для сгенерированного кода...
какой из них быстрый зависит от того, какую версию == вы используете. Вот фрагмент кода, который использует 2 возможных реализации==, и в зависимости от того, хотите ли вы вызвать x == 0 или 0 == x, выбирается один из 2.
Если вы просто используете стручок, это действительно не должно иметь значения, когда речь заходит о скорости.
#include <iostream> using namespace std; class x { public: bool operator==(int x) { cout << "hello\n"; return 0; } friend bool operator==(int x, const x& a) { cout << "world\n"; return 0; } }; int main() { x x1; //int m = 0; int k = (x1 == 0); int j = (0 == x1); }
Ну, я полностью согласен со всем сказанным в комментариях к ОП, ради упражнения:
если компилятор недостаточно умен (действительно, Вы не должны его использовать) или оптимизация отключена,
x == 0может компилироваться в собственную сборкуjump if zeroинструкция, в то время как0 == xможет быть более общим (и дорогостоящим) сравнение числовых значений.тем не менее, я не хотел бы работать на босса, который думает в этих терминах...
конечно, никакой разницы с точки зрения скорости выполнения. Состояние должно быть оценено в обоих случаях одинаково.
Я думаю, что лучший ответ - "на каком это языке пример"?
в вопросе не указан язык, и он помечен как "C", так и " C++". Точный ответ требует больше информации.
это паршивый вопрос программирования, но это может быть хорошо в хитром "давайте дадим интервьюируемому достаточно веревки, чтобы либо повеситься, либо построить качели на дереве". Проблема с такими вопросами заключается в том, что они обычно записываются и передаются из рук в руки интервьюер к интервьюеру, пока он не доберется до людей, которые на самом деле не понимают его со всех сторон.
построить две простые программы, используя предложенные способы.
собрать коды. Посмотрите на сборку, и вы можете судить, но я сомневаюсь, что есть разница!
интервью становятся ниже, чем когда-либо.
Так же, как в сторону ( я на самом деле думаю, что любой приличный компилятор сделает этот вопрос спорным, так как он его оптимизирует ) использование 0 == флаг над флагом == 0 предотвращает опечатку, когда вы забываете один из = ( т. е. если вы случайно наберете флаг = 0, он будет компилироваться, но 0 = флаг не будет), что я думаю, что это ошибка, которую все сделали в тот или иной момент...
Если вообще была разница, то что мешает компилятору выбрать более быстрый раз? Так что логически никакой разницы быть не может. Вероятно, именно этого и ожидает интервьюер. Это на самом деле блестящий вопрос.
Comments