以下语句在性能方面基本相同吗?
a = a / 10;
或
a /= 10;
答案 0 :(得分:4)
这取决于 - 对于基本类型,任何编译器都应为两者生成相同的代码。
对于用户定义的类型,您可以重载两个运算符以执行不同的操作(请不要),这完全取决于它们的实现方式。
答案 1 :(得分:1)
这取决于编译器。可能猜测,大多数编译器将从两个指令生成相同的代码。
尝试对此代码进行基准测试或查看汇编代码,在每种情况下生成什么代码。
例如,Microsoft Visual Studio 2013处于调试模式:
i = i / 20;
011F43C5 mov eax,dword ptr [i]
011F43C8 cdq
011F43C9 mov ecx,14h
011F43CE idiv eax,ecx
011F43D0 mov dword ptr [i],eax
i /= 20;
011F43D3 mov eax,dword ptr [i]
011F43D6 cdq
011F43D7 mov ecx,14h
011F43DC idiv eax,ecx
011F43DE mov dword ptr [i],eax
如果我们讨论用户类型,情况会发生变化,因为您可以为这两个运算符实现不同的算法。在这种情况下,性能严格取决于具体实施。
答案 2 :(得分:1)
让我们进行小测试。我使用的是gcc 4.7.3版本。
我希望a /= 10
等于a = a / 10
。我们可以通过使用-S
参数
int main() {
int a;
a = a / 10;
}
将给出
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl -4(%rbp), %ecx
movl $1717986919, %edx
movl %ecx, %eax
imull %edx
sarl $2, %edx
movl %ecx, %eax
sarl $31, %eax
movl %edx, %ecx
subl %eax, %ecx
movl %ecx, %eax
movl %eax, -4(%rbp)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
和
int main() {
int a;
a /= 10;
}
给出相同的输出
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl -4(%rbp), %ecx
movl $1717986919, %edx
movl %ecx, %eax
imull %edx
sarl $2, %edx
movl %ecx, %eax
sarl $31, %eax
movl %edx, %ecx
subl %eax, %ecx
movl %ecx, %eax
movl %eax, -4(%rbp)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
总而言之,短操作运算符的差异仅在于可读性,而仅适用于原始运算符。不同性能的好例子是preincrement and postincrement for iterators
答案 3 :(得分:0)
在一般情况下,第二个例子总是更可取。
原因很简单。
对于除内在数据类型之外的任何内容,operator / will(当然应该!)以operator /=实现。
这是因为operator /需要复制,应用operator / =(不要重复自己),然后返回该副本。
a /= 10;
归结为
,而
a = a / 10;
归结为:
您通常会看到如下所示的运算符:
class A {
...
public:
A& operator/=(double rhs) {
_internalThing /= rhs;
return *this;
}
private:
double _internalThing;
};
// binary operators should be free functions
A operator/(A lhs, double rhs) {
lhs /= rhs;
return lhs;
}