条件运算符会导致代码效率降低吗?

发布于 2024-11-28 06:01:14 字数 587 浏览 3 评论 0原文

返回对象时,与 if/else 相比,?: 是否会导致代码效率较低?

Foo if_else()
{
    if (bla)
        return Foo();
    else
        return something_convertible_to_Foo;
}

如果 bla 为 false,则返回的 Foo 直接从 something_convertible_to_Foo 构造。

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

这里,return之后的表达式的类型是Foo,所以我猜如果bla首先会创建一些临时的Foo code> 为 false 会产生表达式的结果,然后必须复制构造该临时变量才能返回函数的结果。这样的分析靠谱吗?

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

Foo if_else()
{
    if (bla)
        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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

凉墨 2024-12-05 06:01:14

无论哪种方式都必须构造临时的 Foo,并且这两种情况都是 RVO 的明确候选者,因此我认为没有任何理由相信编译器在这种情况下无法产生相同的输出。与往常一样,实际编译代码并查看输出是最好的做法。

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.

栩栩如生 2024-12-05 06:01:14

在启用右值引用的情况下,它绝对可以。当两个分支之一是左值而另一个是右值时,无论采用哪种方式,都不会为其中至少一个分支调用正确的函数。当您执行 if 语句方式时,代码将调用正确的移动或复制构造函数来返回。

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.

梦魇绽荼蘼 2024-12-05 06:01:14

虽然我很欣赏汇编输出,但我仍然发现它们有点“太”低级了:)

对于以下代码:

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

这是由 Clang 生成的 LLVM IR

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
}

顺便说一下, llvm 尝试演示 现在使用 Clang :p

因为这不是第一次以某种形式出现这个问题,我想记住因为从语义上讲,这两种形式都是同样,就优化和代码生成而言,好的编译器没有理由以不同的方式对待它们。三元运算符只是语法糖。

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.

澜川若宁 2024-12-05 06:01:14

与往常一样,在性能问题中:针对当前的情况进行衡量,进行任何预测时需要考虑太多的事情。

在这里,我不会感到惊讶的是,某些编译器在一种形式或另一种形式上存在问题,而其他编译器则快速获得相同的内部表示形式,从而生成完全相同的代码。

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.

凯凯我们等你回来 2024-12-05 06:01:14

如果有任何差异,我会感到惊讶,因为两者在逻辑上是等效的。但这取决于编译器。

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

紫竹語嫣☆ 2024-12-05 06:01:14

这取决于编译器。据我所知,在大多数编译器上,if-else 都会被转换为更干净的 ASM 代码,而且速度更快。

编辑:假设下面的代码

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

将像这样在 ASM 中翻译

    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 
    }

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 
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文