92

In C++, is the ?: operator faster than if()...else statements? Are there any differences between them in compiled code?

Thomas Padron-McCarthy
  • 27,232
  • 8
  • 51
  • 75
Xirdus
  • 2,997
  • 6
  • 28
  • 36
  • Difficult question, as it would also depend on the optimalisation setting of the compiler. – extraneon Aug 25 '10 at 11:35
  • 3
    That certainly depends on what you do inside the branches. The conditional operator allows only expressions while `if` allows statements. – Gumbo Aug 25 '10 at 11:37
  • 4
    related: [To ternary or not to ternary?](http://stackoverflow.com/questions/160218/to-ternary-or-not-to-ternary) – Nick Dandoulakis Aug 25 '10 at 11:57
  • 12
    Some guy randomly decided to edit my perfectly okay three years old question, rewriting the question so it sounds totally unlike me and adding some totally unnecessary code that makes the whole problem pointless because, thanks to constant folding, both those samples reduce to simple "result = 5". Reverting. – Xirdus Jul 10 '13 at 13:08
  • Assembly version cmov vs jmp http://stackoverflow.com/questions/14131096/why-is-a-conditional-move-not-vulnerable-for-branch-prediction-failure – Ciro Santilli OurBigBook.com May 19 '16 at 10:21

14 Answers14

109

It is not faster. There is one difference when you can initialize a constant variable depending on some expression:

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

You can't do the same with if-else.

Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
  • Yep, with "if-else" first initialization with some default value then assignment of a new value. A few more processor cycles spent. –  Aug 25 '10 at 11:39
  • 22
    @Developer Art: Which isn't possible with a `const` variable. – mtvec Aug 25 '10 at 11:43
  • 1
    You could create a non-const variable, assign to it in the if/else, then create a new const variable and construct it with the non-const. Rather wasteful, but far from impossible. – Puppy Aug 25 '10 at 12:56
  • @DeadMG, in the end you will get one more variable in the same scope, which couldwill be confusing. This is not the same. – Kirill V. Lyadvinsky Aug 25 '10 at 13:00
  • 1
    I said that it was wasteful. You've given just one example of a way in which it is a waste. But it's absolutely not impossible. – Puppy Aug 25 '10 at 13:28
  • What about when initializing a const member? – UncleBens Aug 25 '10 at 16:28
  • @DeadMG: You cannot write an Integral Constant Expression with `if/else`, but you can with `?:` . That is the real difference. Practical: `char foo[ a < b ? b : a ];` cannot be rewritten with if/else; the declarations would end up in the wrong scopes. – MSalters Aug 26 '10 at 09:09
  • Nor can it be written with ?:, because [] needs to be not just const but constexpr, which the result of ?: isn't, unless both a and b are constexprs, in which case, ?: won't compile to any machine code. Edit: There's also alloca, the argument of which is runtime. – Puppy Aug 26 '10 at 09:25
  • 7
    What about good ol' `max`? `const int x = max(a,b);` works just fine. – bobobobo Dec 20 '12 at 23:06
  • 3
    @bobobobo ha! when i read your comment i thought the command you wre suggesting was `max ? const int x = max(a,b);` and thought whoa! WTF is that! then i read it again and noticed the question mark wasn't monospace! given the topic, i think i was justified in thinking the ? was part of the command! :) – dewd Dec 05 '14 at 12:50
  • 2
    You can use `const int x = [&] -> int { if (a < b) return b; else return a; }`. – L. F. Jul 24 '19 at 11:02
  • int& c = a ? a : b; you can't do the same with if-else too. – Nolan Hyde Jun 23 '22 at 09:51
  • @L.F. despite you forgot to invoke it. – apple apple Jul 27 '22 at 17:05
94

Depends on your compiler, but on any modern compiler there is generally no difference. It's something you shouldn't worry about. Concentrate on the maintainability of your code.

ptomato
  • 56,175
  • 13
  • 112
  • 165
  • 1
    +1 For many applications, the perf difference is not worth considering even on a really dump compiler. –  Aug 25 '10 at 11:48
  • 4
    Regarding maintainability of code I'd prefer if...else. At least for me it is easier to read. – Exa Aug 25 '10 at 12:08
  • 3
    @Exa: Depends on the context. The ternary operator is often better when you are initializing an object. – Nemanja Trifunovic Aug 25 '10 at 12:24
  • @Nemanja: That's why I said "At least for me". I was just referring to the readability of code :) – Exa Aug 25 '10 at 12:45
  • May I please ask, HOW is a conditional less maintainable than an "if"? If you have two equal options, consistently choosing the slower one is premature pessimization. – Johan Kotlinski Aug 25 '10 at 13:23
  • 2
    @kotlinski, I'm not saying a conditional is less maintainable than an if. They are both clearer in certain, differing, circumstances, as described in the answers of the _To ternary or not to ternary_ question linked above. – ptomato Aug 25 '10 at 13:41
  • I came a cross an [example](http://stackoverflow.com/questions/11914691/copy-elision-move-constructor-not-called-when-using-ternary-expression-in-retur) in which ternary selection prevented move construction from being used, resulting in extra copies compared to an if/else. – Christopher Johnson Mar 05 '16 at 15:50
  • quite old post already. However, I read [this answer](http://stackoverflow.com/a/7627218/4117728) and I dont understand why there is a difference between ternary and if-else when it comes to deducing the return type (see section "Return Types"). I wanted to ask a question on that, but then I found this one and now I am a bit unsatisfied with the answer ;) – 463035818_is_not_an_ai Sep 03 '16 at 11:15
  • The difference can matter in an embedded system, where it can be the difference between a temporary variable being created or elided. – Pharap May 19 '23 at 22:18
47

I've seen GCC turn the conditional operator into cmov (conditional move) instructions, while turning if statements into branches, which meant in our case, the code was faster when using the conditional operator. But that was a couple of years ago, and most likely today, both would compile to the same code.

There's no guarantee that they'll compile to the same code. If you need the performance then, as always, measure. And when you've measured and found out that 1. your code is too slow, and 2. it is this particular chunk of code that is the culprit, then study the assembly code generated by the compiler and check for yourself what is happening.

Don't trust golden rules like "the compiler will always generate more efficient code if I use the conditional operator".

jalf
  • 243,077
  • 51
  • 345
  • 550
  • 4
    +1. When I was developing for PS3 using GCC, using conditionals instead of "if" was useful to avoid branches. – Johan Kotlinski Aug 25 '10 at 13:21
  • Is this specific to c language? The standard of c++ says `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.` Which apparently prevent the compiler from generating a `cmove` instructions. – Joey.Z Aug 03 '15 at 03:46
  • 3
    @zoujyjs no, C has the same rule. But under the as-if rule, the compiler is free to cheat, as long as the end result is correct. So as long as there are no side effects, the compiler can make this optimization. – jalf Aug 03 '15 at 11:18
  • How to implement if else with cmov? A mov to value 1 + a cmov to value 2 ? – Ciro Santilli OurBigBook.com May 19 '16 at 10:36
  • 1
    NOTE : This advice is outdated (cira 2010), I could not reproduce this on gcc 4.4 or later. – ACyclic Oct 12 '16 at 18:35
17

They are the same, however, the ternary operator can be used in places where it is difficult to use a if/else:

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

Doing that statement with an if/else, would generate a very different compiled code.


Update after 8 years...

Actually, I think this would be better:

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

(actually, I'm pretty sure you can replace the "%d" in the first string with "one")

James Curran
  • 101,701
  • 37
  • 181
  • 258
  • 8
    Doesn't even need a ternary operator: `printf("Total: %d item%s", cnt, "s" + (cnt==1));` – MSalters Aug 26 '10 at 09:15
  • @MSalters but that gives a double null at the end of the string, which may be a problem in _other_ situations where double null means something (eg in `lpStrFilter` member of [OPENFILENAME structures](http://msdn.microsoft.com/en-us/library/ms646839(VS.85).aspx)) – bobobobo Feb 19 '12 at 17:30
  • 1
    @bobobobo: No. `%s` prints up to, but not including the `\0` from the source string. – MSalters Feb 20 '12 at 08:33
  • @MSalters how does this `printf("Total: %d item%s", cnt, "s" + (cnt==1));` work? – Quirk Aug 11 '15 at 02:55
  • 3
    @Quirk: `(cnt==1)` is true or false, which converts to 0 or 1. "s" is a pointer to a nul-terminated string. Adding one skips one character (the s). So this prints either "s" or "". – MSalters Aug 11 '15 at 07:14
  • @MSalters I would hate to review your code. I'd have to think through all the tricks! I mean, kudos, but I don't want my jr devs doing that! – Azeroth2b Aug 30 '23 at 13:21
4

Regardless the compiled code, They are semantically different thing. <cond>?<true expr>:<false expr> is an expression and if..else.. is a statement.

Although the syntax of conditional expression seems awkward, it is a good thing. You are forced to provide a <false expr> and the two expressions are type checked.

The equivalent to if..else.. in expression-based, functional language like Lisp, Haskell is ? : in C++, instead of if..else.. statement.

amdyes
  • 201
  • 1
  • 5
3

Just to be a bit left handed...

x ? y : x = value

will assign value to y if x is not 0 (false).

VS3
  • 47
  • 1
  • 3
    Not without parenthesis: http://stackoverflow.com/questions/7499400/ternary-conditional-and-assignment-operator-precedence – Jerry Jeremiah Nov 20 '15 at 01:35
  • 1
    Wrong (see https://stackoverflow.com/a/7499505/2436175). Besides, what has it to do with the question? – Antonio Jan 21 '18 at 09:57
1

You are not forced to put it all on one line:-

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

It is much clearer than if/else because you can see immediately that both branches lead to x being assigned to.

You can also declare a const eg

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

And a const can be useful to the compiler to make the code more optimised.

QuentinUK
  • 2,997
  • 21
  • 20
0

I think that there are situations where the inline if can yield "faster" code because of the scope it works at. Object creation and destruction can be costly so consider the follow scenario :

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;
}

With this code, the output will be :

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

So by inlining the if, we save a bunch of operation needed to keep a alive at the same scope as b. While it is highly probable that the condition evaluation speed is pretty equal in both scenarios, changing scope forces you to take other factors into consideration that the inline if allows you to avoid.

Eric
  • 19,525
  • 19
  • 84
  • 147
0

I would expect that on most compilers and target platforms, there will be cases where "if" is faster and cases where ?: is faster. There will also be cases where one form is more or less compact than the other. Which cases favor one form or the other will vary between compilers and platforms. If you're writing performance-critical code on an embedded micro, look at what the compiler is generating in each case and see which is better. On a "mainstream" PC, because of caching issues, the only way to see which is better is to benchmark both forms in something resembling the real application.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

In C A ternary operator " ? : " is available to construct conditional expressions of the form

exp1 ? exp2:exp3

where exp1,exp2 and exp3 are expressions

for Example

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

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

This can be written using if..else statement as follows

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

**Hence there is no difference between these two. This for the programmer to write easily, but for compiler both are same.*

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
ksrao
  • 101
  • 3
0

During reversing some code (which I don't remember, few years ago) I saw single line difference between the Machine Code of :? and if-else. Don't remember much but it is clear that implementation of both is different.

But I advise You to not choose one of them b'coz of its efficiency, choose according to readability of code or your convenience. Happy Coding

Pervez Alam
  • 1,246
  • 10
  • 20
  • The difference was one of them was using goto for branching and other was using saome native instruction, I don't remember which one was using which.. – Pervez Alam Jan 19 '12 at 12:44
0

Ternary Operator always returns a value. So in situation when you want some output value from result and there are only 2 conditions always better to use ternary operator. Use if-else if any of the above mentioned conditions are not true.

-1

Now I can't help you with that, I may be able to help with a secondary question beneath it, do I want to use it? If you just want to know of the speed, just ignore my comment.

All I can say is please be very smart about when to use the ternary ? : operator. It can be a blessing as much as a curse for readability.

Ask yourself if you find this easier to read before using it

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

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

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

Yes It looks stupid to make the code 100% bogus. But that little trick helped me analyse my readability of code. It's the readability of the operator you look at in this sample, and not the content.

It LOOKS clean, but so does the average toilet seat and doorknob

In my experience, which is limited, I have seen very little people actually being able to quickly extradite information required from a ternary operator, avoid unless 100% sure it's better. It's a pain to fix when it's bugged aswell I think

Proclyon
  • 526
  • 5
  • 12
  • 5
    first line should probably read `int x = x == 1 ? 1 : 2` or possibly `int x = (x == 1) ? 1 : 2` – Hasturkun Aug 25 '10 at 12:35
  • My point was merely to show the view of the code, the cleanlyness of one line is nice yes. But if you want to see CONDITION / ASSIGNEMENT the content of the code can be bogus. If you want to spot what is what you look at the operator and the location alone. I see the word IF and ( ) I know , ah , that is a condition. I see A = B ? CONDITION : CONDITION did you immedeatly spot that for yourself? Most people I know that program do not, maybe it's because most people I know that program are rookies like me. You are correct ofc in the numbers being nonsense, thats the point. – Proclyon Aug 25 '10 at 12:59
  • 2
    First line definitely needs some parentheses. Perhaps "int x = (y==1) ? 0 : 1;" or "int x = ((y==1) ? 0 : 1);" – supercat Aug 25 '10 at 15:09
  • 6
    I'm sorry, but I have no problem seeing the assignment. If you choose to overcomplicate the example to make your point, that's your problem. Why don't you write `x = x = 1;` everywhere and then complain that assignment is too complicated and should be avoided. – UncleBens Aug 25 '10 at 16:32
-5

No, they are converted to exactly the same executable code.

Alex F
  • 42,307
  • 41
  • 144
  • 212