我正在阅读Stroustrup的“ C ++编程语言”,他说在两种向变量添加内容的方法中
x = x + a;
和
x += a;
他喜欢,+=因为它很可能会更好地实施。我认为他的意思是它的运行速度也更快。
但是真的吗?如果它取决于编译器和其他因素,如何检查?  
我正在阅读Stroustrup的“ C ++编程语言”,他说在两种向变量添加内容的方法中
x = x + a;
和
x += a;
他喜欢,+=因为它很可能会更好地实施。我认为他的意思是它的运行速度也更快。
但是真的吗?如果它取决于编译器和其他因素,如何检查?  
Answers:
任何编译器称职将产生完全相同的两个构建任何内置类型(同样的机器语言程序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);
而x = x + a翻译成
auto TEMP(x.operator+(a));
x.operator=(TEMP);
现在,如果正确编写了类,并且编译器的优化器足够好,那么两者都将生成相同的机器语言,但是并不能像内置类型那样确定。这可能是Stroustrup鼓励使用时的想法+=。
expr到var是var+=expr,写它的其他方式将读者糊涂。
                    *f() = *f() + a;,则可能不妨认真研究一下您真正想要实现的目标……
                    1是一个常数,a可以是易失性,用户定义的类型或其他类型。完全不同。实际上,我什至不知道这是怎么结束的。
                    您可以通过查看dissasembly检查,这是相同的。
对于基本类型,两者都同样快。
这是调试版本生成的输出(即没有优化):
    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 +=,这取决于它们各自的实现。
a为1,x则volatile编译器可以生成inc DWORD PTR [x]。太慢了
                    operator +任何操作,并operator +=计算第100000个素数,然后返回。当然,这将是一件愚蠢的事情,但这是可能的。
                    ++x和之间的性能差异很敏感temp = x + 1; x = temp;,那么很可能应该用汇编而不是c ++来编写...
                    之间的区别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,编译器作者赞赏它,当你刚刚说你的意思。这样,您就不会行使编译器的编写者希望他/她摆脱了所有错误的那一部分,并且这实际上并不会使您的生活更轻松,除非您坦白地说无法直截了当Fortran模式。
举一个具体的例子,想象一个简单的复数类型:
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的情况,它必须制作一个额外的临时变量,然后将其复制。
您问错了问题。
这不太可能提高应用程序或功能的性能。即使是这样,找出问题的方法是分析代码并确定它对您的影响。与其在此级别上担心哪个速度更快,不如从清晰度,正确性和可读性方面考虑更为重要。
当您考虑到即使这是重要的性能因素时,编译器也会随着时间的推移而发展,这一点尤其正确。有人可能会想出一种新的优化方法,今天正确的答案明天可能会出错。这是过早优化的经典案例。
这并不是说性能根本不重要……只是实现您的绩效目标是错误的方法。正确的方法是使用分析工具来了解代码实际在哪里花费时间,从而在哪里集中精力。