验证 C++ 内置类型的函数传参时用传值方式效率较高

在《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 0;
}

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

     4: int f(int i)
     5: {
00F343D0  push        ebp
00F343D1  mov         ebp,esp
00F343D3  sub         esp,0CCh
00F343D9  push        ebx
00F343DA  push        esi
00F343DB  push        edi
00F343DC  lea         edi,[ebp-0CCh]
00F343E2  mov         ecx,33h
00F343E7  mov         eax,0CCCCCCCCh
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
00F34400  ret

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

    10: int 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: }
......

传引用 传指针

    16: int 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: }
......

指针跟上面引用一样。

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

pass by value

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

时间: 2024-10-16 10:50:40

验证 C++ 内置类型的函数传参时用传值方式效率较高的相关文章

对Python和Go的函数传参研究

传参一直是语言中有点纠结的东西.一提到这个,总会有人说,需要区分传值,传递引用,还有传递指针什么的.而且,貌似不同的语言对此也有不同的实现. 我自己也对这个有点搞混了,所以需要实验一下. 写在开头: 我常用的几个语言是,C++,Go语言,python这几种.三个语言中,只有C++有引用,而Python是没有指针的.参数传递主要就两类,传值和传递引用. 本文只写Python和Go语言,C++太复杂了,需要专门研究. 试验的主要分为几种类型,分别为: 单一的变量类型,比如int,float这种基本类

mysql limit函数传参问题

问题描述 mysql limit函数传参问题 limit函数有限制参数必须为整型,现在有个需求是要给limit函数传入二个参数,而我这边能提供的二个参数是string型的,如果转化为int性被limit函数接受? 用cast(? as unsigned int)不行,求高手赐教 解决方案 啥语言? //php intval/int //java Integer.valueof(String) //js parseInt() //c++ sprintf/itoa

php使用$_POST或$_SESSION[]向js函数传参_php技巧

在php编程中向js函数传参可以使用$_POST也可使用$_SESSION[' '],也可用echo语句进行输出 复制代码 代码如下: <?php echo "<script>test('$_POST[userid]');</script> "; ?> 在上面的$_POST['']也可适用$_SESSION[' ']; 复制代码 代码如下: <?php $para = "hello boby!"; echo $para; /

JavaScript中使用arguments获得函数传参个数实例_javascript技巧

JS与PHP在函数传参方面有点不同,PHP形参与实参个数要匹配,而JS就灵活多了,可以随意传参,实参比形参少或多都不会报错. 实参比形参多不会报错 function say(a){    alert(a); }   say('琼台博客','WEB技术博客'); 执行结果 我们再来看看形参比实参多的结果 function say(a,b){    alert('a 的值是 '+a+'\nb 的值是 '+b); }   say('琼台博客'); 执行结果 a 对应第一个实参"琼台博客",b

c语言-C语言函数传参使用_()是什么意思?

问题描述 C语言函数传参使用_()是什么意思? 比如有的printf函数这样写: printf(_("......"), .......); 解决方案 c语言是什么意思 解决方案二: 你写错了吧?是这样吧? printf(_T("......"), .......); 可参考:http://blog.sina.com.cn/s/blog_95d87c800101076h.html

php向js函数传参的几种方法_php技巧

<?php echo "<script>test('$_POST[userid]');</script> "; ?> 在上面的$_POST['']也可适用$_SESSION[' ']; <?php $para = "hello boby!"; echo $para; echo "<script> var para=\"$para\"; alert(para);</script&

PHP闭包函数传参及使用外部变量的方法_php技巧

本文实例讲述了PHP闭包函数传参及使用外部变量的方法.分享给大家供大家参考,具体如下: 在Laravel控制器写两个方法,一个是在内部创建一个闭包函数,一个是执行传过来的闭包函数,测试闭包的写法,use使用外部变量,及闭包函数的传参.如下: //测试闭包传参及use使用外部变量 public function testClosure($t1, $t2) { $closure = function ($param1, $param2) use ($t1, $t2) { echo $param1.$

JavaScript函数传参、作用域的教程

函数传参小示例一: fnA(1,2);  fnA(2,3);  function fnA(a,b)  {      alert(a+b);  }  函数传参小实例一: CSS: body,ul{margin:0;padding:0;}  li{ list-style:none;}  .box{width:200px; margin:20px auto;}  .box ul{ height:30px;}  .box li{width:50px;height:30px;background:#ccc

《从缺陷中学习C/C++》——6.3 数组传参时的sizeof

6.3 数组传参时的sizeof 从缺陷中学习C/C++ 代码示例 void copy(int a[], int b[]) { memcpy(b, a, sizeof(a)); } 现象&结果 copy函数执行后,内存中的内容与设想不符,目标数组b中的内容不完整,没有把源数组a中的内容全部复制过来. Bug分析 memcpy函数的原型是void memcpy(void dest, const void *src, size_t n);,它的功能是从源src所指的内存地址的起始位置开始复制n个字节