循环效率的 C++:主体与事后想法

c++ for loop efficiency: body vs. afterthought

本文关键字:事后 主体 效率 C++ 循环      更新时间:2023-10-16

我在leetcode上发现了一些有趣的东西,希望有人可以帮助解释原因:

我基本上是在进行合并排序,并使用快速慢速指针来查找中间指针。以下是此类代码片段的两个版本:

1. 事后更新

    for (ListNode* fast=head; 
         fast->next && fast->next->next; 
         fast = fast->next->next, slow = slow->next) { }

2. 正文更新

    for (ListNode* fast=head; fast->next && fast->next->next; ) {
        fast = fast->next->next;
        slow = slow->next;
    }

为什么版本 2 比第一个更快?

编译器:g++ 4.9.2

逗号操作不太可能显着降低 for 循环的速度。

我已经制作了这两种变体并打开了反汇编(在Visual Studio 2012中),以便他们看到差异。

  1. 看起来像:

        for (ListNode* fast = head;
    0022545E  mov         eax,dword ptr [head]  
    00225461  mov         dword ptr [ebp-2Ch],eax  
            fast->next && fast->next->next;
    00225464  jmp         main+17Bh (022547Bh)  
            fast = fast->next->next, slow = slow->next) {
    00225466  mov         eax,dword ptr [ebp-2Ch]  
    00225469  mov         ecx,dword ptr [eax+4]  
    0022546C  mov         edx,dword ptr [ecx+4]  
    0022546F  mov         dword ptr [ebp-2Ch],edx  
    00225472  mov         eax,dword ptr [slow]  
    00225475  mov         ecx,dword ptr [eax+4]  
    00225478  mov         dword ptr [slow],ecx  
    0022547B  mov         eax,dword ptr [ebp-2Ch]  
    0022547E  cmp         dword ptr [eax+4],0  
    00225482  je          main+192h (0225492h)  
    00225484  mov         eax,dword ptr [ebp-2Ch]  
    00225487  mov         ecx,dword ptr [eax+4]  
    0022548A  cmp         dword ptr [ecx+4],0  
    0022548E  je          main+192h (0225492h)  
        }
    
  2. 是:

        for (ListNode* fast = head; fast->next && fast->next->next;) {
    0024545E  mov         eax,dword ptr [head]  
    00245461  mov         dword ptr [ebp-2Ch],eax  
    00245464  mov         eax,dword ptr [ebp-2Ch]  
    00245467  cmp         dword ptr [eax+4],0  
    0024546B  je          main+190h (0245490h)  
    0024546D  mov         eax,dword ptr [ebp-2Ch]  
    00245470  mov         ecx,dword ptr [eax+4]  
    00245473  cmp         dword ptr [ecx+4],0  
    00245477  je          main+190h (0245490h)  
            fast = fast->next->next;
    00245479  mov         eax,dword ptr [ebp-2Ch]  
    0024547C  mov         ecx,dword ptr [eax+4]  
    0024547F  mov         edx,dword ptr [ecx+4]  
    00245482  mov         dword ptr [ebp-2Ch],edx  
            slow = slow->next;
    00245485  mov         eax,dword ptr [slow]  
    00245488  mov         ecx,dword ptr [eax+4]  
    0024548B  mov         dword ptr [slow],ecx  
        }
    

区别只有一个jmp。抱歉,但我看不到显着差异,因此性能问题可能不在这两个语句的位置。