Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是x+;=a比x=x+快;A. 我读了Stroustrup的《C++程序设计语言》,他说 向变量添加内容的两种方法中的任意一种 x = x + a;_C++_Performance_Operators - Fatal编程技术网

是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 */
}