2010-08-25 3 views
57

В C++ оператор is: быстрее, чем if() ... else. Существуют ли различия между ними в скомпилированном коде?Тернарный оператор?: Vs if ... else

+0

Трудный вопрос, так как это также зависит от настройки оптимализации компилятора. – extraneon

+3

Это, безусловно, зависит от того, что вы делаете внутри ветвей. Условный оператор допускает только выражения, а 'if' допускает утверждения. – Gumbo

+3

Относительно: [К тернарному или не к тернарному?] (Http://stackoverflow.com/questions/160218/to-ternary-or-not-to -ternary) –

ответ

73

Зависит от вашего компилятора, но на любом современном компиляторе, как правило, нет разницы. Это то, о чем вам не стоит беспокоиться. Сосредоточьтесь на ремонтопригодности вашего кода.

+1

+1 Для многих приложений разница в перфорации не стоит рассматривать даже на самом компиляторе дампа. – delnan

+3

Что касается ремонтопригодности кода, я бы предпочел бы, если бы ... еще. По крайней мере, для меня это легче читать. – Exa

+2

@Exa: зависит от контекста. Тройной оператор часто лучше, когда вы инициализируете объект. –

-3

Нет, они преобразуются в один и тот же исполняемый код.

+5

-1: В какой версии какого компилятора, на какой платформе, с каким кодом? – Puppy

+2

DeadMG: компилятор VB6, очевидно! –

87

Это не быстрее. Существует одна разница, когда вы можете инициализировать постоянную переменную в зависимости от некоторого выражения:

const int x = (a<b) ? b : a; 

Вы не можете сделать то же самое с if-else.

+0

Да, с инициализацией «if-else» с некоторым значением по умолчанию, а затем присваиванием нового значения. Прошло еще несколько циклов процессора. – 2010-08-25 11:39:29

+15

@Developer Art: Это невозможно с переменной 'const'. – Job

+1

Вы можете создать неконстантную переменную, назначить ей в if/else, а затем создать новую константную переменную и построить ее с неконстантной. Скорее расточительный, но далекий от невозможности. – Puppy

12

Они же, однако, тройной оператор может использоваться в местах, где трудно использовать, если/другое:

printf("Total: %d item%s", cnt, cnt != 1 ? "s" : ""); 

Делая это заявление с, если/иначе, будет генерировать очень другой скомпилированный код.

+6

Даже не нужен тройной оператор: 'printf (" Total:% d item% s ", cnt," s "+ (cnt == 1));' – MSalters

+0

@MSalters, но это дает двойной нуль при конец строки, что может быть проблемой в других ситуациях, когда двойной null означает что-то (например, в элементе 'lpStrFilter' [структуры OPENFILENAME] (http://msdn.microsoft.com/en-us/library/ms646839 (VS.85) .aspx)) – bobobobo

+1

@bobobobo: Нет. '% S' печатает до, но не включает' \ 0' из исходной строки. – MSalters

35

Я видел, что GCC превратил условный оператор в инструкции cmov (условное перемещение), а при повороте if операторов в ветви, что означало в нашем случае, код был быстрее при использовании условного оператора. Но это было пару лет назад, и, скорее всего, сегодня оба будут компилироваться по одному и тому же коду.

Невозможно скомпилировать тот же код. Если вам нужна производительность, то, как всегда, мер. И когда вы измерили и узнали, что 1. ваш код слишком медленный, и 2. именно этот кусок кода является виновником, затем изучите код сборки, сгенерированный компилятором, и проверьте сами, что происходит.

Не доверяйте золотым правилам, например «компилятор всегда будет генерировать более эффективный код, если я использую условный оператор».

+1

+1. Когда я разрабатывал PS3, используя GCC, использование условных выражений вместо «if» было полезно избежать ветвей. –

+0

Это специфично для языка c? В стандарте C++ говорится: «Оценивается только одно из второго и третьего выражений. Каждое значение вычисление и побочный эффект, связанные с первым выражением, секвенируются перед вычислением каждого значения и побочным эффектом, связанным со вторым или третьим выражением. «Это, по-видимому, не позволяет компилятору генерировать команды cmove. – zoujyjs

+2

@zoujyjs no, C имеет то же правило. Но в соответствии с правилом as-if компилятор может обманывать, если конечный результат верен. Таким образом, пока нет побочных эффектов, компилятор может сделать эту оптимизацию. – jalf

0

Теперь я не могу с этим поделать, я могу помочь с дополнительным вопросом под ним, хочу ли я его использовать? Если вы просто хотите узнать о скорости, просто игнорируйте мой комментарий.

Все, что я могу сказать, это быть очень умным, когда использовать тройной? : оператор. Это может быть благословением, а также проклятием для удобочитаемости.

Спросите себя, если вы найдете это легче читать, прежде чем использовать его

int x = x == 1 ? x = 1 : x = 1; 

if (x == 1) 
{ 
    x = 1 
} 
else 
{ 
    x = 2 
} 

if (x == 1) 
    x = 1 
else 
    x = 1 

Да, это выглядит глупо, чтобы сделать код 100% поддельным. Но этот небольшой трюк помог мне проанализировать мою читаемость кода. Это читаемость оператора, на который вы смотрите в этом примере, а не на контент.

Это выглядит чистое, но так же среднее сиденье для унитаза и дверной ручкой

В моем опыте, который ограничен, я видел очень мало людей на самом деле быть в состоянии быстро выдавать информацию, требуемую от тройного оператора, не избежать, если 100% уверен, что это лучше. Это боль, чтобы исправить, когда она прослушивается, я думаю,

+5

Первая строка должна, вероятно, читать 'int x = x == 1? 1: 2' или, возможно, 'int x = (x == 1)? 1: 2' – Hasturkun

+0

Моя точка зрения состояла в том, чтобы просто показать вид кода, чистота одной строки - это хорошо. Но если вы хотите видеть CONDITION/ASSIGNEMENT, содержимое кода может быть фиктивным. Если вы хотите узнать, что вы смотрите на оператора и на место в одиночку. Я вижу слово IF и() Я знаю, ах, это условие. Я вижу A = B? СОСТОЯНИЕ: СОСТОЯНИЕ Вы сразу заметили это для себя? Большинство людей, которых я знаю, что программа не делает, может быть, это потому, что большинство людей, которых я знаю, это новички, подобные мне. Вы правы в цифрах, которые нонсенс, это точка. – Proclyon

+2

Первая строка определенно нуждается в некоторых скобках. Возможно, «int x = (y == 1)? 0: 1;» или "int x = ((y == 1)? 0: 1);" – supercat

0

Я ожидал бы, что на большинстве компиляторов и целевых платформ будут случаи, когда «если» быстрее, а случаи где?: Быстрее.Будут также случаи, когда одна форма более или менее компактна, чем другая. Какие случаи относятся к одной форме или другой, будут различаться между компиляторами и платформами. Если вы пишете критически важный код на встроенном микропроцессе, посмотрите, что генерирует компилятор в каждом случае, и посмотрите, что лучше. На «мейнстримовом» ПК из-за проблем с кешированием единственный способ увидеть, что лучше, - это сопоставить обе формы с чем-то похожим на реальное приложение.

-1

В тройном оператора CA ":" можно построить условные выражения вида

exp1 ? exp2:exp3 

где exp1, ехр2 и exp3 являются выражениями

для примера

 a=20; 
     b=25; 
     x=(a>b)?a:b; 

     in the above example x value will be assigned to b; 

Это может быть записано с использованием if..else:

  if (a>b) 
      x=a; 
      else 
      x=b; 

** Следовательно, нет никакой разницы между этими двумя. Это просто для программиста, но для компилятора оба они одинаковы. *

0

Во время реверсирования некоторого кода (который я не помню, несколько лет назад) я видел разницу в одной строке между машинным кодом:? и if-else. Don't remember much but it is clear that implementation of both is different.

Но я советую вам не выбирать один из них b'coz своей эффективности, выбирать в соответствии с читабельностью кода или вашего удобства. Happy Code

+0

Разница заключалась в том, что с помощью goto для ветвления использовалась goto, а другая использовала встроенную инструкцию saome, я не помню, какой из них использовал. –

0

Тернарный оператор всегда возвращает значение. Итак, в ситуации, когда вам нужно какое-то выходное значение из результата, и только 2 условия всегда лучше использовать тернарный оператор. Используйте if-else, если какое-либо из вышеупомянутых условий неверно.

+5

Что это такое? Вы знаете, о чем говорите? – quantum

3

Просто быть немного левшой ...

x ? y : x = value 

присвоит значение к у если х не 0 (ложь).

+0

Вы уверены? ... – Xirdus

+2

Не без круглых скобок: http://stackoverflow.com/questions/7499400/ternary-conditional-and-assignment-operator-precedence –

+0

Неверно (см. Https://stackoverflow.com/a/ 7499505/2436175). Кроме того, что это касается вопроса? – Antonio

0

Я думаю, что есть ситуации, когда inline if может получить «более быстрый» код из-за области, в которой он работает. Создание объектов и уничтожение может быть дорогостоящим, поэтому рассмотреть последующую ситуацию:

class A{ 
    public: 
    A() : value(0) { 
     cout << "Default ctor" << endl; 
    } 
    A(int myInt) : value(myInt) 
    { 
     cout << "Overloaded ctor" << endl; 
    } 

    A& operator=(const A& other){ 
     cout << "= operator" << endl; 
     value = other.value; 
    } 

    ~A(){ 
     cout << "destroyed" << std::endl; 
    } 

    int value; 

}; 


int main() 
{ 
    { 
     A a; 
     if(true){ 
      a = A(5); 
     }else{ 
      a = A(10); 
     } 
    } 

    cout << "Next test" << endl; 
    { 
     A b = true? A(5) : A(10); 
    } 
    return 0; 
} 

С помощью этого кода, на выходе будет:

Default ctor                                                      
Overloaded ctor                                                     
= operator                                                       
destroyed                                                       
destroyed                                                       
Next test                                                       
Overloaded ctor                                                     
destroyed 

Итак, встраивание КРП, мы экономим кучу операций, необходимых для держите a живыми в том же объеме, что и b. Хотя очень вероятно, что скорость оценки состояния довольно одинакова в обоих сценариях, изменение сферы действия заставляет вас учитывать другие факторы, что встроенный, если позволяет избежать.

+0

А как насчет 'A a (true? 5: 10);' – Quest

0

Вы не обязаны поставить все это на одной линии: -

x = y==1 ? 
    2 
    :// else 
    3; 

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

2

Независимо от скомпилированного кода, они семантически отличаются друг от друга. <cond>?<true expr>:<false expr> - выражение, а if..else.. - это утверждение.

Хотя синтаксис условного выражения кажется неудобным, это хорошо. Вы вынуждены предоставить <false expr>, и два выражения проверяются по типу.

Эквивалент if..else.. в функциональном языке, основанном на выражениях, например Lisp, Haskell равен ? : в C++, а не if..else...

Смежные вопросы