C++中三种传递参数方法的效率分析

c/c++

浏览数:157

2019-8-9

众所周知,在C++中有三种参数传递的方式:

  • 按值传递(pass by value)
#include <iostream>
using namespace std;

void swap(int a,int b)
{
    int temp = a;
    a = b;
    b = temp;
}
int main()
{
    int a = 0, b = 1;
    cout << a << " " << b << endl;
    swap(a,b);
    cout << a << " " << b << endl;
    return 0;
}


最好理解的一种方式。调用函数本身不对实参进行操作,也就是说,即使形参的值在函数中发生了变化,实参的值也完全不会受到影响,仍为调用前的值。

  • 按址传递(pass by pointer)
#include <iostream>
using namespace std;

void swap(int* a,int* b)
{
   int* temp = a;
   a = b;
   b = temp;
}

int main()
{
   int a = 0, b = 1;
   cout << a << " " << b << endl;
   swap(a,b);
   cout << a << " " << b << endl;
   return 0;
}


这种方式在函数定义时将形参说明成指针。把实参的存储地址传送给对应的形参,从而使得形参指针和实参指针指向同一个地址。因此,被调用函数中对形参指针所指向的地址中内容的任何改变都会影响到实参

  • 引用传递(pass by reference)
#include <iostream>
using namespace std;

void swap(int &a,int &b)
{
    int temp = a;
    a = b;
    b = temp;
}

int main()
{
    int a = 0, b = 1;
    cout << a << " " << b << endl;
    swap(a,b);
    cout << a << " " << b << endl;
    return 0;
}


引用传递方式是在函数定义时在形参前面加上引用运算符“&”。如果以引用为参数,则既可以使得对形参的任何操作都能改变相应的数据,又使得函数调用显得方便、自然。
本文主要讨论采用这三种方法传递参数时函数的效率。

传递效率

这里所说传递效率,是说调用被调函数的代码将实参传递到被调函数体内的过程,正如上面代码中,这个过程就是函数main()中的 a、b 传递到函数swap()中的过程。这个效率不能一概而论。对于内建的 int char、short、long、float 等4字节或以下的数据类型而言,实际上传递时也只需要传递 1-4 个字节,而使用指针传递时在 32 位 cpu 中传递的是 32 位的指针,4 个字节,都是一条指令,这种情况下值传递和指针传递的效率是一样的,而传递 double、long long 等 8 字节的数据时,在 32 位 cpu 中,其传值效率比传递指针要慢,因为 8 个字节需要 2 次取完。而在 64 位的 cpu 上,传值和传址的效率是一样的。再说引用传递,这个要看编译器具体实现,引用传递最显然的实现方式是使用指针,这种情况下与指针的效率是一样的,而有些情况下编译器是可以优化的,采用直接寻址的方式,这种情况下,效率比传值调用和传址调用都要快,与采用全局变量方式传递的效率相当。

再说自定义的数据类型 —— class struct 定义的数据类型。这些数据类型在进行传值调用时生成临时对象会执行构造函数,而且当临时对象销毁时会执行析构函数,如果构造函数和析构函数执行的任务比较多,或者传递的对象尺寸比较大,那么传值调用的消耗就比较大。这种情况下,采用传址调用和采用传引用调用的效率大多数下相当,正如上面所说,某些情况下引用传递可能被优化,总体效率稍高于传址调用。

执行效率

这里所说的执行效率,是指在被调用的函数体内执行时的效率。 因为传值调用时,当值被传到函数体内,临时对象生成以后,所有的执行任务都是通过直接寻址的方式执行的,而指针和大多数情况下的引用则是以间接寻址的方式执行的,所以实际的执行效率会比传值调用要低。如果函数体内对参数传过来的变量进行操作比较频繁,执行总次数又多的情况下,传址调用和大多数情况下的引用参数传递会造成比较明显的执行效率损失。

综上所述,具体的执行效率要结合实际情况,通过比较传递过程的资源消耗和执行函数体消耗之和来选择哪种情况比较合适。而就引用传递和指针传递的效率上比,引用传递的效率始终不低于指针传递,所以从这种意义上讲,在c++中进行参数传递时优先使用引用传递而不是指针。

参考:C++中函数调用时的三种参数传递方式详解

作者:闽A2436