开发者

Can the conditional operator lead to less efficient code?

Can ?: lead to less efficient code compared to if/else when returning an object?

Foo if_else()
{
    if (bla)开发者_StackOverflow社区
        return Foo();
    else
        return something_convertible_to_Foo;
}

If bla is false, the returned Foo is directly constructed from something_convertible_to_Foo.

Foo question_mark_colon()
{
    return (bla) ? Foo() : something_convertible_to_Foo;
}

Here, the type of the expression after the return is Foo, so I guess first some temporary Foo is created if bla is false to yield the result of the expression, and then that temporary has to be copy-constructed to return the result of the function. Is that analysis sound?


A temporary Foo has to be constructed either way, and both cases are a clear candidate for RVO, so I don't see any reason to believe the compiler would fail to produce identical output in this case. As always, actually compiling the code and looking at the output is the best course of action.


It most definitely can where rvalue references are enabled. When one of the two branches is an lvalue and the other an rvalue, whichever way you go, you're going to not get the correct function called for at least one of them. When you do the if statement way, then the code will call the correct move or copy constructor for the return.


While I appreciate assembly output, I still find them a bit "too" low-level :)

For the following code:

struct Foo { Foo(): i(0) {} Foo(int i): i(i) {} int i; };
struct Bar { Bar(double d): d(d) {} double d; operator Foo() const { return Foo(d); } };

Foo If(bool cond) {
  if (cond) { return Foo(); }
  return Bar(3);
}

Foo Ternary(bool cond) {
  return cond ? Foo() : Bar(3);
}

Here is the LLVM IR generated by Clang

define i64 @If(bool)(i1 zeroext %cond) nounwind readnone {
entry:
  %retval.0.0 = select i1 %cond, i64 0, i64 3     ; <i64> [#uses=1]
  ret i64 %retval.0.0
}

define i64 @Ternary(bool)(i1 zeroext %cond) nounwind readnone {
entry:
  %tmp.016.0 = select i1 %cond, i64 0, i64 3      ; <i64> [#uses=1]
  ret i64 %tmp.016.0
}

By the way, the llvm try out demo now uses Clang :p

Since it is not the first time that the question comes up, in one form or another, I would like to remember that since semantically both forms are equivalent, there is no reason for a good compiler to treat them any differently as far as optimization and code generation are concerned. The ternary operator is just syntactic sugar.


As always in case of performance question: measure for the case at hand, there are too many things to take into account to do any prediction.

Here, I'd not be surprised that some compilers have problems with one form or the other while others get rapidly to the same internal representation and thus generate exactly the same code.


I will be surprised if there is any difference since the two are logically equivalent. But this will depend on the compiler.


It depends on compiler. As far as i know, on most of compilers, if-else it's translated to cleaner ASM code and it's faster.

Edit: Assuming the code below

int a = 10;
int b = 20;
int c = 30;
int d = 30;
int y = 30;

y = (a > b) ? c : d;

if (a > b)
{
    y = c;
}
else
{
    y = d;
}

will be translated in ASM like this

    y = (a > b) ? c : d;
008C13B1  mov         eax,dword ptr [a] 
008C13B4  cmp         eax,dword ptr [b] 
008C13B7  jle         wmain+54h (8C13C4h) 
008C13B9  mov         ecx,dword ptr [c] 
008C13BC  mov         dword ptr [ebp-100h],ecx 
008C13C2  jmp         wmain+5Dh (8C13CDh) 
008C13C4  mov         edx,dword ptr [d] 
008C13C7  mov         dword ptr [ebp-100h],edx 
008C13CD  mov         eax,dword ptr [ebp-100h] 
008C13D3  mov         dword ptr [y],eax 

    if (a > b)
008C13D6  mov         eax,dword ptr [a] 
008C13D9  cmp         eax,dword ptr [b] 
008C13DC  jle         wmain+76h (8C13E6h) 
    {
        y = c;
008C13DE  mov         eax,dword ptr [c] 
008C13E1  mov         dword ptr [y],eax 
    }
    else
008C13E4  jmp         wmain+7Ch (8C13ECh) 
    {
        y = d;
008C13E6  mov         eax,dword ptr [d] 
008C13E9  mov         dword ptr [y],eax 
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜