C++ 函数传参为何传值反而更高效?

2021-07-20 00:00:00 函数 代码 高效 地址 指针

在《Effective C++》里提到对内置(C-like)类型在函数传参时 pass by value 比  pass by reference 更高效。

一般不是传引用会更高效吗?为什么反而传值更高效。

当用OO的c++自定义类型(存在构造/析构等) pass by reference to const 更好。

STL里的迭代器和函数对象是用C指针实现的,因此 pass by value更好。

至于为什么,下面的代码验证了:

#include <iostream>
using namespace std;

int f(int i)
{
   int r = i + 1;
   return r;
}

int g(const int & i)
{
    int r = i + 1;
    return r;
}

int h(int * p)
{
    int r = * p + 1;
    return r;
}

int inter(int * &p)
{
    int r = * p + 1;
    return r;
}

int main()
{
    int i = 0x11111111;
    f(i);
    g(i);
    h(&i);

    int * x = &i;
    r = inter(x);
    return ;
}

用VS 2012 默认Debug配置下生成的汇编代码如下:

     4int f(int i)
     5
{
00F343D  push        ebp 
00F343D1  mov         ebp,esp 
00F343D3  sub         esp,CCh 
00F343D9  push        ebx 
00F343DA  push        esi 
00F343DB  push        edi 
00F343DC  lea         edi,[ebp-0CCh
00F343E2  mov         ecx,33h 
00F343E7  mov         eax,CCCCCCCCh 
00F343EC  rep stos    dword ptr es:[edi
     6:    int r = i + 1;
00F343EE  mov         eax,dword ptr [i]  //直接将i的值取出来给eax
00F343F1  add         eax,1  //eax+1
00F343F4  mov         dword ptr [r],eax 
     7:    return r;
00F343F7  mov         eax,dword ptr [r] 
     8: }
00F343FA  pop         edi 
00F343FB  pop         esi 
00F343FC  pop         ebx 
00F343FD  mov         esp,ebp 
00F343FF  pop         ebp 
00F3440  ret

后面的几个函数,只截取了关键代码了。

    10int g(const int &i)
    11: 

 ...... 
    12:     int r = i + 1;
00F3449E  mov         eax,dword ptr [i]  // 跟传指针一样,取i的地址到eax
00F344A1  mov         ecx,dword ptr [eax]  // 将eax的值取出来 放到ecx中
00F344A3  add         ecx,1  // ecx值+1
00F344A6  mov         dword ptr [r],ecx 
    13:     return r;
00F344A9  mov         eax,dword ptr [r] 
    14: }
......
 16int h(int * p)
    17: 
{
......
    18:     int r = *p + 1;
00F3453E  mov         eax,dword ptr [p]         // 取p的地址,让到eax中
00F34541  mov         ecx,dword ptr [eax]   //把eax的值取出来,让到ecx中
00F34543  add         ecx,1   //exc的值+1
00F34546  mov         dword ptr [r],ecx 
    19:     return r;
00F34549  mov         eax,dword ptr [r] 
    20: }

指针跟上面引用一样。

    22int inter(int * &p)
    23
{
......
    24:     int r = *p + 1;
01233DBE  mov         eax,dword ptr [p]  //取传进参数(指针)的地址-&gt;eax
01233DC1  mov         ecx,dword ptr [eax] //取参数指针的地址--&gt;ecx, (是真正值的地址)
01233DC3  mov         edx,dword ptr [ecx]  //取ecx的内容-&gt;edx
01233DC5  add         edx,1 //edx 值+1
01233DC8  mov         dword ptr [r],edx 
    25:     return r;
01233DCB  mov         eax,dword ptr [r] 
    26: }
......

从汇编代码可以看出,为啥内置类型作为函数参数传递时更高效。

好了,全文完,今天你学到了吗?

欢迎关注,每天进步一点点,离大厂近一点点。

以上文章来源于公众号程序员升级打怪  

相关文章