是x+;=a比x=x+快;A. 我读了Stroustrup的《C++程序设计语言》,他说 向变量添加内容的两种方法中的任意一种 x = x + a;
及 他更喜欢是x+;=a比x=x+快;A. 我读了Stroustrup的《C++程序设计语言》,他说 向变量添加内容的两种方法中的任意一种 x = x + a;,c++,performance,operators,C++,Performance,Operators,及 他更喜欢+=,因为它很可能实现得更好。我想他的意思是,它也工作得更快。 但真的吗?如果它取决于编译器和其他东西,我如何检查 您可以通过查看dissasembly进行检查,这将是相同的 对于基本类型,两者速度相同 这是调试生成生成的输出(即无优化): 类型> >,在这里你可以重载操作符+< /COD>和操作符+= ,这取决于它们各自的实现。 < P>不,两种方式都得到相同的处理。 < P>当你标记了这个C++时,你无法从你所发表的两个语句中知道。你需要知道“x”是什么(有点像答案“42”)。
+=
,因为它很可能实现得更好。我想他的意思是,它也工作得更快。但真的吗?如果它取决于编译器和其他东西,我如何检查 您可以通过查看dissasembly进行检查,这将是相同的 对于基本类型,两者速度相同 这是调试生成生成的输出(即无优化):
<用户>类型> <强> >,在这里你可以重载<代码>操作符+< /COD>和<代码>操作符+= ,这取决于它们各自的实现。 < P>不,两种方式都得到相同的处理。 < P>当你标记了这个C++时,你无法从你所发表的两个语句中知道。你需要知道“x”是什么(有点像答案“42”)。如果
x
是一个豆荚,那么它实际上不会有多大区别。但是,如果x
是一个类,那么操作符+
和操作符+=
方法可能会有重载,这些方法可能具有不同的行为,从而导致非常不同的执行时间。这实际上取决于x和a的类型以及+的实现。为了
T x, a;
....
x = x + a;
编译器必须创建一个临时T来包含x+a的值,同时对其进行求值,然后将其分配给x。(在此操作期间,它不能将x或a用作工作区)
对于x+=a,它不需要临时变量
对于普通类型,没有区别。任何称职的编译器都会为任何内置类型(
int
,float
,等等)的两个构造生成完全相同的机器语言序列,只要语句真的像x=x+a代码>和优化已启用。(值得注意的是,GCC的默认模式是-O0
,它执行反优化,例如将完全不必要的存储插入内存,以确保调试器始终可以找到变量值。)
不过,如果陈述更为复杂,它们可能会有所不同。假设f
是一个返回指针的函数,那么
*f() += a;
只调用f
一次,而
*f() = *f() + a;
叫了两次。如果f
有副作用,那么两种药物中的一种可能是错误的(可能是后者)。即使f
没有副作用,编译器也可能无法消除第二次调用,因此后者的速度可能确实较慢
既然我们这里讨论C++,那么对于过载类型< >代码>运算符+< /COD>和<代码>运算符+= 的情况完全不同。如果
x
是这样一种类型,那么在优化之前--x+=a
转换为
x.operator+=(a);
auto TEMP(x.operator+(a));
x.operator=(TEMP);
而x=x+a
转换为
x.operator+=(a);
auto TEMP(x.operator+(a));
x.operator=(TEMP);
现在,如果类编写正确,并且编译器的优化器足够好,那么两者最终都会生成相同的机器语言,但这并不像内置类型那样确定。这可能是Stroustrup在鼓励使用+=
时所想的x=x+a
和x+=a
之间的区别在于机器必须完成的工作量-一些编译器可能(通常也确实)对其进行优化,但通常,如果我们忽略优化一段时间,发生的情况是,在前一个代码段中,机器必须查找x
的值两次,而在后一个代码段中,此查找只需进行一次
然而,正如我提到的,今天大多数编译器都足够智能,能够分析指令并减少所需的机器指令
PS:关于堆栈溢出的第一个答案 你问错问题了
这不太可能提高应用程序或功能的性能。即使是这样,找到答案的方法是对代码进行分析,并确定它对您的影响。与其在这个层面上担心哪一个更快,不如从清晰性、正确性和可读性的角度来思考
<>这是特别的,当你考虑到,即使这是一个重要的性能因素,编译器也会在一段时间内进化。有人可能会想出一个新的优化方案,今天正确的答案明天可能会变成错误的。这是一个典型的过早优化案例
这并不是说性能根本不重要。。。只是这是实现你的绩效目标的错误方法。正确的方法是使用分析工具来了解代码实际花费的时间,从而了解您的工作重点。如果您说+=
,那么编译器的工作就轻松多了。为了让编译器识别x=x+a
与x+=a
相同,编译器必须
- 分析左侧(
x
)以确保其没有副作用,并且始终指向相同的l值。例如,它可以是z[i]
,它必须确保z
和i
都不改变
- 分析右手边(
x+a
)并确保它是一个求和,并且左手边在右手边出现一次且仅出现一次,即使它可以转换,如z[i]=a+*(z+2*0+i)
如果您的意思是将a
添加到x
,那么当您说出您的意思时,编译器编写者会非常感激。
那样的话,你就不会去练习编译器的编写者希望他/她能从中排除所有bug的那部分,而这实际上并不会让你的生活变得更轻松,除非你真的无法摆脱Fortran模式。我认为这应该取决于机器及其体系结构。如果它的体系结构允许间接内存寻址,编译器编写器可能会
mov $[y],$ACC
iadd $ACC, $[i] ; i += y. WHICH MIGHT ALSO STORE IT INTO "i"
mov $[i],$ACC
mov $[y],$B
iadd $ACC,$B
mov $B,[i]
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 */
}