为什么后缀增量比C++中的前缀增长得快?

Ser*_*sak -5 c++

我一直认为,必须相反.但当我尝试这个简单的代码时,我得到了意想不到的结果:

#include <cstdlib>
#include <cstdio>

#include <iostream>

#include <chrono>

using namespace std;


int main(int argc, char* argv[])
{
  int x = 0, y = 0;
  double z;
  chrono::steady_clock::time_point start_point;

  start_point = chrono::steady_clock::now();

  for(int i = 0; i < 100000; x = ++i)
    for(int j = 0; j < 100000; y = ++j)
      z = static_cast<double>(x * y);

  cout << "The prefix increment took a " << chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_point).count() << " milliseconds" << endl;

  start_point = chrono::steady_clock::now();

  for(int i = 0; i < 100000; x = i++)
    for(int j = 0; j < 100000; y = j++)
      z = static_cast<double>(x * y);

  cout << "The postfix increment took a " << chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_point).count() << " milliseconds" << endl;

  // To make the compiler happy...
  x = y = static_cast<int>(z / z);

  cout << "SUCCESS" << endl;
  return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

在我的机器上运行此代码的结果是:

The prefix increment took a 25716 milliseconds
The postfix increment took a 19119 milliseconds
SUCCESS
Run Code Online (Sandbox Code Playgroud)

编辑:

是的,改变z = ...z += ...含铅到的执行时间变得相等.

谢谢大家的回答.

Bat*_*eba 13

完全没有区别 - 任何感知差异都是由于您的测试技术引入的工件.

编译器已经多年来一直在优化i++(虽然我仍然++i习惯于习惯).不要测试这样的事情 - 设置框架太困难了.简化程序并检查生成的程序集.

还需要注意的是用32位的平台上int(很常见)的代码的行为是由于未定义int溢出(100,000平方比31大 2的幂).这使您的测试完全无用.

  • @SergeRoussak:是的,你的测试毫无根据.为什么你继续坚持这样的观点,即你是正确的,并且发现i ++比++ i更快?来吧,要认真! (8认同)
  • @SergeRoussak当我运行你的代码我得到它们都花了0毫秒.你的测试是错误的. (3认同)
  • 提示:(1)修复UB,(2)`cout <<"前缀增量采用"引入*很多*的开销.(3)对x和y的每个值做更多:也许*sum*它们为`z`?(4)多次复制你的两个循环.(5)切换运行顺序. (2认同)

Tho*_*kow 7

添加只有少数什么拔示巴已经表示,无论是

int i;
i++
Run Code Online (Sandbox Code Playgroud)

int i;
++i
Run Code Online (Sandbox Code Playgroud)

得到编译

push rbp
mov rbp, rsp
add DWORD PTR [rbp-4], 1
Run Code Online (Sandbox Code Playgroud)

其中增加值的重要线是

add DWORD PTR [rbp-4], 1
^^^                   ^^^
relevant             parts
Run Code Online (Sandbox Code Playgroud)

在回答关于优化您的评论,上面的代码与优化关闭 ; 使用-O导致

add DWORD PTR [rdi], 1
^^^                 ^^^
relevant           parts
Run Code Online (Sandbox Code Playgroud)

对于i++++i.我不得不调整样本

void F(int& i)
{
    ++i; // respectively i++
}
Run Code Online (Sandbox Code Playgroud)

因为它没有被完全优化,但重点仍然是相同的.


我用过gcc 7.3 x86-64.使用Online Compiler Explorer自行测试.

  • 这是令人信服的(+1),但请注意这里的编译器细节和目标架构. (3认同)