来源:唐磊的个人博客《C++ 传参时传内置类型时用传值(pass
by value)方式效率较高》

在《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: }
......



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

C++ 传参时传内置类型时用传值(pass by value)方式效率较高的更多相关文章

  1. Go语言的传参和传引用[转]

    目录[-] 传参和传引用的问题 传slice不是传引用! 什么叫传引用? 为什么传slice不是传引用? 为什么很多人误以为slice是传引用呢? 传指针和传引用是等价的吗? 所有类型的函数参数都是传 ...

  2. 上有传参下传json的接口调用

    1.优化Myrequest import requests from conf.setting import log class MyRequest(): @staticmethod def post ...

  3. Vue路由传参及传参后刷新导致参数消失处理

    项目功能需要,要从列表页跳转到第三方提供的URL上(这里第三方页面我是通过iframe引入在详情页,目的是点击返回时可以通过keepAlive让列表页不刷新,如果不通过iframe直接跳第三方链接,那 ...

  4. vue传参子传父

    vue子传父用$emit实现 1.文件目录结构 2.parent父组件内容 <template> <div class="wrap"> <div> ...

  5. cocos2dx 菜单按钮回调方法传参 tag传参

    .h文件 void menuCallBack(CCObject* pSender); .cpp CCMenuItemSprite* item = CCMenuItemSprite::create( m ...

  6. vue.js 传参 href传参 与router-link传参

    每天学习一点点 编程PDF电子书免费下载: http://www.shitanlife.com/code 1. <a v-bind:href="'#/appinfo/'+cateApp ...

  7. vue-router4 |name的作用|query传参|parmas传参|动态路由参数|命名视图|别名alias|前置路由守卫|路由过渡效果|滚动行为

    vue-router4 出现 No match found for location with path "/" #### router/index.ts文件 import { c ...

  8. python函数传参是传值还是传引用?

    首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传 ...

  9. Postman 串行传参和动态传参详解

    Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件 用Postman做接口测试的时候,要把多条用例一起执行,就需要把用例连接起来,一次性执行 目录 串行传参 动态传参 使用 ...

随机推荐

  1. [OpenCV]在显示窗口中截图

    [OpenCV]在显示窗口中截图 简介 介绍使用OpenCV实现简单的截图功能.首先阐述实现此功能的基本步骤,然后给出实现代码,最后贴出实验结果以及遇到的问题. 基本步骤 我们需要知道OpenCV使用 ...

  2. 不可错过的Node.js框架

    前言 Node.js是由Ryan Dahl于2009年创建的.它是一个开源的跨平台运行时环境,用于开发服务器端和网络应用程序,它是基于Google Chrome V8 JavaScript引擎构建的. ...

  3. 使用Intent传递对象

    Intent 的用法相信你已经比较熟悉了,我们可以借助它来启动活动.发送广播.启动服务等.在进行上述操作的时候,我们还可以在Intent 中添加一些附加数据,以达到传值的效果,比如在FirstActi ...

  4. tomcat自动运行磁盘任意位置上的项目、使用Maven对tomcat进行自动部署

     对于非Maven的web项目,有时候我们想不时常通过打war包.拷贝war包.启动tomcat来运行项目.这时候我们可以通过以下方式来进行配置: 1.1:创建web工程.工程结构如下: 1.2. ...

  5. Java安全管理器——SecurityManager

    总的来说,Java安全应该包括两方面的内容,一是Java平台(即是Java运行环境)的安全性:二是Java语言开发的应用程序的安全性.由于我们不是Java本身语言的制定开发者,所以第一个安全性不需要我 ...

  6. 看见的力量 – (I) 解题的思维

    本文转自台湾李智桦老师的博客,原文地址 这篇文章:已经梗了我三个多星期了.这期间飞了二次大陆做演讲.往返几个大城市做教授敏捷开发运用在精实创业的课程.教材内容都是简体的,它们始终没有机会在国内用上,心 ...

  7. Spring入门介绍-AOP(三)

    AOP的概念 AOP是面向切面编程的缩写,它是一种编程的新思想.对我们经常提起的oop(面对对象编程)有一定的联系. AOP和OOP的关系 AOP可以说是oop的某一方便的补充,oop侧重于对静态的属 ...

  8. 算法之路(二)呈现O(logN)型的三个算法

    典型时间复杂度 我们知道算法的执行效率,可以从它的时间复杂度来推算出一二.而典型的时间复杂度有哪些类型呢? 由上图,可以看出,除了常数时间复杂度外,logN型的算法效率是最高的.今天就介绍三种非常ea ...

  9. 线程在Linux中的实现

          早在以前,我们就知道,CPU调度的基本单位是线程,而进程是拥有资源的基本单位,进程是用进程描述符表示的,那么线程是怎么实现和表示的呢?       线程机制是现代编程技术中常用的一种抽象概 ...

  10. tomcat配置集群

    在Tomcat中使用集群功能相对简单.最简单的用法是直接在server.xml文件的或节点下添加 <Cluster className="org.apache.catalina.ha. ...