返回对象时?:
代码与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
,因此我想首先创建一些临时Foo
,如果bla
为false则产生结果表达式,然后临时必须进行复制构造以返回函数的结果。那分析听起来不错?
答案 0 :(得分:8)
必须以任一方式构造临时Foo
,并且这两种情况都是RVO的明确候选者,因此我认为没有任何理由相信编译器在这种情况下将无法生成相同的输出。与往常一样,实际编译代码并查看输出是最好的操作过程。
答案 1 :(得分:4)
绝对可以启用右值引用。当两个分支中的一个是左值而另一个是左值时,无论你采用哪种方式,你都不会得到至少其中一个所需的正确函数。当您执行if语句方式时,代码将为返回调用正确的移动或复制构造函数。
答案 2 :(得分:3)
虽然我很欣赏汇编输出,但我仍然发现它们有点“太”低级别:)
以下代码:
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 try out demo现在使用了Clang:p
由于这不是第一次以某种形式提出问题,我想记住,因为语义上两种形式都是等价的,所以 good 编译器没有理由就优化和代码生成而言,以不同的方式对待它们。三元运算符只是语法糖。
答案 3 :(得分:2)
与性能问题一样:对手头的案例进行衡量,做任何预测都需要考虑太多事情。
在这里,我不会感到惊讶的是,有些编译器会遇到一种形式或另一种形式的问题,而其他编译器会快速进入相同的内部表示,从而生成完全相同的代码。
答案 4 :(得分:0)
如果两者在逻辑上等同,我会感到惊讶。但这取决于编译器。
答案 5 :(得分:-1)
这取决于编译器。据我所知,在大多数编译器上,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
}