是x+=a比x=x+a快吗
Is x += a quicker than x = x + a?
我在读Stroustrup的《C++编程语言》,他说向可变添加内容的两种方法
x = x + a;
和
x += a;
他更喜欢+=
,因为它很可能实现得更好。我想他的意思是它也能更快地工作
但真的吗?如果它取决于编译器和其他东西,我该如何检查?
任何值得一试的编译器都会为任何内置类型(int
、float
等)的两个构造生成完全相同的机器语言序列,只要语句真的像x = x + a;
一样简单并且启用了优化。(值得注意的是,GCC的-O0
是默认模式,它执行反优化,例如向内存插入完全不必要的存储,以确保调试器始终可以找到变量值。)
不过,如果语句更复杂,它们可能会有所不同。假设f
是一个返回指针的函数,那么
*f() += a;
只调用f
一次,而
*f() = *f() + a;
调用两次。如果f
有副作用,那么两者中的一个是错误的(可能是后者)。即使f
没有副作用,编译器也可能无法消除第二个调用,因此后者可能确实较慢。
由于我们在这里讨论的是C++,所以重载operator+
和operator+=
的类类型的情况完全不同。如果x
是这样一种类型,那么在优化之前,x += a
转换为
x.operator+=(a);
而CCD_ 14转化为
auto TEMP(x.operator+(a));
x.operator=(TEMP);
现在,如果类被正确地编写和,编译器的优化器就足够好了,两者最终都会生成相同的机器语言,但这并不像内置类型那样确定。这可能是Stroustrup在鼓励使用+=
时的想法。
您可以通过查看disassembly进行检查,这将是相同的。
对于基本类型,两者速度相同。
这是由调试构建生成的输出(即没有优化):
a += x;
010813BC mov eax,dword ptr [a]
010813BF add eax,dword ptr [x]
010813C2 mov dword ptr [a],eax
a = a + x;
010813C5 mov eax,dword ptr [a]
010813C8 add eax,dword ptr [x]
010813CB mov dword ptr [a],eax
对于可以重载operator +
和operator +=
的用户定义类型,这取决于它们各自的实现。
x = x + a
和x += a
之间的区别在于机器必须完成的工作量-一些编译器可能(通常也会这样做)对其进行优化,但通常,如果我们暂时忽略优化,会发生的情况是,在前一个代码段中,机器必须查找x
的值两次,而在后一个代码片段中,此查找只需要发生一次。
然而,正如我所提到的,如今大多数编译器都足够智能,可以分析指令并减少所需的机器指令。
PS:堆栈溢出的第一个答案!
是!对于后者来说,在x
可能有副作用的情况下,它写得更快,读得更快,弄清楚也更快。所以它对人类来说总体上更快。一般来说,人类的时间比计算机的时间要花得多,所以这一定是你所问的。正确的
它实际上取决于x和a的类型以及+的实现。对于
T x, a;
....
x = x + a;
编译器必须创建一个临时T来包含x+a的值,同时对其进行求值,然后将其分配给x。(在此操作期间,它不能将x或a用作工作区)。
对于x+=a,它不需要临时的。
对于琐碎的类型,没有区别。
如果你说+=
,你会让编译器的生活变得更轻松。为了让编译器识别出x = x+a
与x += a
相同,编译器必须进行
-
分析左手侧(
x
)以确保它没有副作用,并且总是指相同的l值。例如,它可能是z[i]
,并且它必须确保z
和i
都不会更改。 -
分析右手边(
x+a
)并确保它是一个求和,并且左手边在右手边出现一次且仅出现一次,即使它可以变换,如z[i] = a + *(z+2*0+i)
中所示。
如果您的意思是将a
添加到x
,那么当您说出您的意思时,编译器编写器会很感激。这样一来,您就没有使用编译器的编写者希望清除所有错误的部分,而且实际上并没有让您的生活变得更轻松,除非您真的无法摆脱Fortran模式。
正如您所标记的C++,从您发布的两条语句中无法得知。你需要知道"x"是什么(这有点像答案"42")。如果x
是POD,那么它不会有太大区别。然而,如果x
是一个类,则可能存在operator +
和operator +=
方法的过载,这两种方法可能具有不同的行为,从而导致非常不同的执行时间。
对于一个具体的例子,想象一个简单的复数类型:
struct complex {
double x, y;
complex(double _x, double _y) : x(_x), y(_y) { }
complex& operator +=(const complex& b) {
x += b.x;
y += b.y;
return *this;
}
complex operator +(const complex& b) {
complex result(x+b.x, y+b.y);
return result;
}
/* trivial assignment operator */
}
对于a=a+b的情况,它必须制作一个额外的临时变量,然后复制它
你问错了问题。
这不太可能提高应用程序或功能的性能。即使是这样,找到答案的方法也是评测代码,并确定它对您的影响。与其在这个级别上担心哪一个更快,不如从清晰性、正确性和可读性的角度思考更重要。
当您考虑到即使这是一个重要的性能因素,编译器也会随着时间的推移而发展时,情况尤其如此。有人可能会想出一个新的优化方案,而今天的正确答案明天可能会变成错误。这是过早优化的典型案例。
这并不是说性能根本不重要。。。只是这是实现绩效目标的错误方法。正确的方法是使用评测工具来了解代码实际花费的时间,从而了解您的工作重点。
我认为这应该取决于机器及其体系结构。如果其体系结构允许间接内存寻址,编译器编写器可能只使用以下代码(用于优化):
mov $[y],$ACC
iadd $ACC, $[i] ; i += y. WHICH MIGHT ALSO STORE IT INTO "i"
然而,i = i + y
可能会被翻译为(无需优化):
mov $[i],$ACC
mov $[y],$B
iadd $ACC,$B
mov $B,[i]
也就是说,还应该考虑其他复杂情况,例如
i
是否是返回指针的函数等。大多数生产级编译器,包括GCC,为两个语句生成相同的代码(如果它们是整数)。不,两种方法都是一样的。
- 对于 http 请求,python 比 c++ 快吗?
- 如果要求比较器是严格的总排序,而不仅仅是严格的弱排序,C++标准算法会更快吗?
- 假设 a 是双倍的,2.0*a 比 2*a 快吗?
- “std::p ow(double, int)”比“std::p ow(double, double)”快吗?如果是,快
- 类方法变量,如果将它们存储在类本身中会更快吗?
- 在 GPU 上计算积分图像真的比在 CPU 上更快吗?
- C 中的unordered_map/set的哈希功能更快吗?
- C++映射:创建一个临时变量或每次使用键访问值会更快吗
- 是x+=a比x=x+a快吗
- Qt:QML比c++小部件快吗
- 模块会使模板编译更快吗
- CUDA内核2x2 ZgemmBatched:比CuBLAS快5倍.它能跑得更快吗
- 在实践中,无序映射真的比映射快吗
- isdigit() 在 c++ 中不应该更快吗?
- "!="比较运算符比">"快吗?
- 循环真的比递归快吗?
- 使用二进制堆从数组中获取前x个整数会更快吗?还是使用快速排序
- 如果程序中没有结构,c++代码运行得更快吗?< / h1 >
- 如果没有if,std::count_if会更快吗
- 乘法比浮点除法快吗