通过值传递比通过引用传递更快 [英] Pass by value faster than pass by reference

查看:195
本文介绍了通过值传递比通过引用传递更快的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用c ++编写了一个简单的程序来比较两种方法的性能-按值传递和按引用传递。

I made a simple program in c++ to compare performance between two approaches - pass by value and pass by reference. Actually pass by value performed better than pass by reference.

结论应该是按价值传递需要更少的时钟周期(指令)。

The conclusion should be that passing by value require fewer clock-cycles (instructions)

如果有人能够详细解释为什么按值传递需要更少的时钟周期,我将非常高兴。

I would be really glad if someone could explain in detail why pass by value require fewer clock-cycles.

#include <iostream>
#include <stdlib.h>
#include <time.h>

using namespace std;

void function(int *ptr);
void function2(int val);

int main() {

   int nmbr = 5;

   clock_t start, stop;
   start = clock();
   for (long i = 0; i < 1000000000; i++) {
       function(&nmbr);
       //function2(nmbr);
   }
   stop = clock();

   cout << "time: " << stop - start;

   return 0;
}

/**
* pass by reference
*/
void function(int *ptr) {
    *ptr *= 5;
}

/**
* pass by value
*/
void function2(int val) {
   val *= 5;
}


推荐答案

找出答案的好方法为什么会有任何差异是要检查拆卸情况。这是我在使用Visual Studio 2012的计算机上获得的结果。

A good way to find out why there are any differences is to check the disassembly. Here are the results I got on my machine with Visual Studio 2012.

使用优化标志,两个函数都会生成相同的代码:

With optimization flags, both functions generate the same code:

009D1270 57                   push        edi  
009D1271 FF 15 D4 30 9D 00    call        dword ptr ds:[9D30D4h]  
009D1277 8B F8                mov         edi,eax  
009D1279 FF 15 D4 30 9D 00    call        dword ptr ds:[9D30D4h]  
009D127F 8B 0D 48 30 9D 00    mov         ecx,dword ptr ds:[9D3048h]  
009D1285 2B C7                sub         eax,edi  
009D1287 50                   push        eax  
009D1288 E8 A3 04 00 00       call        std::operator<<<std::char_traits<char> > (09D1730h)  
009D128D 8B C8                mov         ecx,eax  
009D128F FF 15 2C 30 9D 00    call        dword ptr ds:[9D302Ch]  
009D1295 33 C0                xor         eax,eax  
009D1297 5F                   pop         edi  
009D1298 C3                   ret  

这基本上等同于:

int main ()
{
    clock_t start, stop ;
    start = clock () ;
    stop = clock () ;
    cout << "time: " << stop - start ;
    return 0 ;
}

没有优化标志,您可能会得到不同的结果。

Without optimization flags, you will probably get different results.

功能(无优化):

00114890 55                   push        ebp  
00114891 8B EC                mov         ebp,esp  
00114893 81 EC C0 00 00 00    sub         esp,0C0h  
00114899 53                   push        ebx  
0011489A 56                   push        esi  
0011489B 57                   push        edi  
0011489C 8D BD 40 FF FF FF    lea         edi,[ebp-0C0h]  
001148A2 B9 30 00 00 00       mov         ecx,30h  
001148A7 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
001148AC F3 AB                rep stos    dword ptr es:[edi]  
001148AE 8B 45 08             mov         eax,dword ptr [ptr]  
001148B1 8B 08                mov         ecx,dword ptr [eax]  
001148B3 6B C9 05             imul        ecx,ecx,5  
001148B6 8B 55 08             mov         edx,dword ptr [ptr]  
001148B9 89 0A                mov         dword ptr [edx],ecx  
001148BB 5F                   pop         edi  
001148BC 5E                   pop         esi  
001148BD 5B                   pop         ebx  
001148BE 8B E5                mov         esp,ebp  
001148C0 5D                   pop         ebp  
001148C1 C3                   ret 

function2(无优化)

function2 (no optimizations)

00FF4850 55                   push        ebp  
00FF4851 8B EC                mov         ebp,esp  
00FF4853 81 EC C0 00 00 00    sub         esp,0C0h  
00FF4859 53                   push        ebx  
00FF485A 56                   push        esi  
00FF485B 57                   push        edi  
00FF485C 8D BD 40 FF FF FF    lea         edi,[ebp-0C0h]  
00FF4862 B9 30 00 00 00       mov         ecx,30h  
00FF4867 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
00FF486C F3 AB                rep stos    dword ptr es:[edi]  
00FF486E 8B 45 08             mov         eax,dword ptr [val]  
00FF4871 6B C0 05             imul        eax,eax,5  
00FF4874 89 45 08             mov         dword ptr [val],eax  
00FF4877 5F                   pop         edi  
00FF4878 5E                   pop         esi  
00FF4879 5B                   pop         ebx  
00FF487A 8B E5                mov         esp,ebp  
00FF487C 5D                   pop         ebp  
00FF487D C3                   ret  

为什么更快地通过值传递(在没有优化的情况下)?

嗯, function()还有两个 mov 操作。让我们看一下第一个额外的 mov 操作:

Well, function() has two extra mov operations. Let's take a look at the first extra mov operation:

001148AE 8B 45 08             mov         eax,dword ptr [ptr]  
001148B1 8B 08                mov         ecx,dword ptr [eax]  
001148B3 6B C9 05             imul        ecx,ecx,5

在这里,我们取消引用指针。在 function2()中,我们已经有了该值,因此可以避免此步骤。我们首先将指针的地址移入寄存器eax。然后,将指针的值移动到寄存器ecx中。最后,我们将值乘以五。

Here we are dereferencing the pointer. In function2 (), we already have the value, so we avoid this step. We first move the address of the pointer into register eax. Then we move the value of the pointer into register ecx. Finally, we multiply the value by five.

让我们看看第二个额外的 mov 操作:

Let's look at the second extra mov operation:

001148B3 6B C9 05             imul        ecx,ecx,5  
001148B6 8B 55 08             mov         edx,dword ptr [ptr]  
001148B9 89 0A                mov         dword ptr [edx],ecx 

现在我们向后移动。我们刚刚将值乘以5,然后需要将值放回内存地址。

Now we are moving backwards. We have just finished multiplying the value by 5, and we need to place the value back into the memory address.

因为 function2()不必处理引用和解引用指针,它可以跳过这两个额外的 mov 操作。

Because function2 () does not have to deal with referencing and dereferencing a pointer, it gets to skip these two extra mov operations.

这篇关于通过值传递比通过引用传递更快的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆