Вопрос по conditional-operator, c++, performance – Тернарный оператор?: Против если ... еще

63

В C ++ оператор?: Быстрее операторов if () ... else? Есть ли различия между ними в скомпилированном коде?

Сложный вопрос, так как это также будет зависеть от настройки оптимизации компилятора. extraneon
Сборочная версия cmov vs jmpstackoverflow.com/questions/14131096/... Ciro Santilli 新疆改造中心996ICU六四事件
Это, безусловно, зависит от того, что вы делаете внутри ветвей. Условный оператор допускает только выражения, в то время какif позволяет заявления. Gumbo
Какой-то парень случайно решил отредактировать мой совершенно нормальный трехлетний вопрос, переписав вопрос так, чтобы он звучал совершенно непохожим на меня, и добавив совершенно ненужный код, который делает всю проблему бессмысленной, потому что, благодаря постоянному сворачиванию, оба эти примера сводятся к простому »результату = 5 ". Откат. Xirdus

Ваш Ответ

13   ответов
-1

В C доступен троичный оператор "?:" Для построения условных выражений вида

exp1 ? exp2:exp3

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

например

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

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

Это может быть написано с помощьюесли еще утверждение следующее

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

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

91

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

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

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

Я сказал, что это расточительно. Вы привели только один пример того, как это пустая трата времени. Но это абсолютно не невозможно. Puppy
Хорошо, что лямбды "решат" это для if / else :) хаха Johannes Schaub - litb
@Developer Art: что невозможно сconst переменная. Job
Вы можете создать неконстантную переменную, присвоить ей в if / else, затем создать новую константную переменную и сконструировать ее с неконстантной. Довольно расточительно, но далеко не невозможно. Puppy
2

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

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

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

0

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

14

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

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

Выполнение этого оператора с помощью if / else приведет к созданию совершенно другого скомпилированного кода.

Обновление через 8 лет ...

На самом деле, я думаю, что это было бы лучше

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

(на самом деле, я уверен, что вы можете заменить «% d» в первой строке на «один»)

@MSalters как этоprintf("Total: %d item%s", cnt, "s" + (cnt==1)); Работа? Quirk
Даже не нужен троичный оператор:printf("Total: %d item%s", cnt, "s" + (cnt==1)); MSalters
Ах да, ты прав. Милая. bobobobo
@Галтель:(cnt==1) Значение true или false, которое преобразуется в 0 или 1. «s» - указатель на строку с нулевым символом в конце. Добавление одного пропускает один символ (ы). Так что это печатает либо "S" или "". MSalters
40

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

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

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

ПРИМЕЧАНИЕ. Этот совет устарел (cira 2010), я не смог воспроизвести его на gcc 4.4 или более поздней версии. ACyclic
@zoujyjs нет, C имеет то же правило. Но по правилу «как будто» компилятор может свободно обманывать, если конечный результат верен. Таким образом, пока нет побочных эффектов, компилятор может выполнить эту оптимизацию. jalf
Как реализовать если еще с CMOV? Мов до значения 1 + смов до значения 2? Ciro Santilli 新疆改造中心996ICU六四事件
+1. Когда я разрабатывал для PS3 с использованием GCC, было полезно использовать условные выражения вместо «если», чтобы избежать переходов. Johan Kotlinski
Это специфично для языка c? Стандарт с ++ говоритOnly one of the second and third expressions is evaluated. Every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression. Что, по-видимому, мешает компилятору генерироватьcmove инструкции. zoujyjs
0

Я думаю, что бывают ситуации, когда встроенный 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  

Таким образом, добавляя if, мы сохраняем кучу операций, необходимых для сохраненияa жив в том же объеме, что иb, Несмотря на то, что весьма вероятно, что скорость оценки состояния в обоих сценариях довольно одинакова, изменение объема вынуждает вас принимать во внимание другие факторы, которые встроенный метод позволяет вам избежать.

И что насчетA a(true ? 5 : 10); Quest
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%, что это лучше. Я думаю, что это трудно исправить, когда она прослушивается

Извините, но у меня нет проблем с просмотром задания. Если вы решите слишком усложнить пример, чтобы высказать свою точку зрения, это ваша проблема. Почему ты не пишешьx = x = 1; везде и потом жалуются, что назначение слишком сложное и его следует избегать. UncleBens
первая строка должна читатьсяint x = x == 1 ? 1 : 2 или возможноint x = (x == 1) ? 1 : 2 Hasturkun
Моя цель была просто показать вид кода, чистота одной строки это хорошо, да. Но если вы хотите увидеть СОСТОЯНИЕ / НАЗНАЧЕНИЕ, содержание кода может быть поддельным. Если вы хотите определить, что именно вы смотрите на оператора и местоположение в одиночку. Я вижу слово IF и () Я знаю, ах, это условие. Я вижу A = B? СОСТОЯНИЕ: СОСТОЯНИЕ вы сами обнаружили это для себя? Большинство людей, которых я знаю, не знают этой программы, возможно, это потому, что большинство людей, которых я знаю, являются такими же новичками, как я. Вы правы ofc в числах, чепуха, вот в чем дело. Proclyon
Первая строка определенно нуждается в скобках. Возможно, "int x = (y == 1)? 0: 1;" или "int x = ((y == 1)? 0: 1);" supercat
0

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

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

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

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

Разница была в том, что один из них использовал goto для ветвления, а другой использовал некоторую нативную инструкцию, я не помню, какая из них использовала какую ... Pervez Alam
2

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

x ? y : x = value

назначитзначение вy еслиx не 0 (ложь).

Уверены ли вы?... Xirdus
Неправильно (см.stackoverflow.com/a/7499505/2436175). Кроме того, какое это имеет отношение к вопросу? Antonio
Не без скобок:stackoverflow.com/questions/7499400/... Jerry Jeremiah
81

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

@Nemanja: Вот почему я сказал «По крайней мере, для меня». Я просто имел в виду читабельность кода :) Exa
Что касается ремонтопригодности кода, я бы предпочел, если ... еще. По крайней мере, для меня это легче читать. Exa
@Exa: зависит от контекста. Тернарный оператор часто лучше, когда вы инициализируете объект. Nemanja Trifunovic
@kotlinski, я не говорю, что условный код менее ремонтопригоден, чем if. Они оба более ясны в определенных, разных обстоятельствах, как описано в ответахК троичной или нет к тройной вопрос связан выше. ptomato
0

Вы не обязаны помещать все это в одну строку:

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

Это намного понятнее, чем if / else, потому что сразу видно, что обе ветви приводят к тому, что x назначается

Вы также можете инициализировать const QuentinUK

Похожие вопросы