关于参数传递

    包括C 和Java在内的许多编程语言都是使用按值调用来传递参数的,即将实参复制给形参。

但是在C++中,参数有可能是大的复杂对象,导致复制的效率很低。另外,有时候又需要改变被传递的值。对此,C++有三种不同的方式来传递参数。有一个简单的规则可以确定具体采用哪种方式。

下面的函数声明阐述了这三种参数传递机制,该函数返回arr中前N个整数的平均值,并且如果N大于arr.size()或者小于1,就设点errorFlag为true:

double avg(const vector<int> & arr, int n, bool & errorFlag);


这里,arr是vector<int>类型的,使用按常量引用调用(call by constant reference)来传递。n是int类型的,通过按值调用来传递。errorFlag是bool类型的,使用引址调用(call by reference)来传递。参数传递机制的选用可以通过一下两步的判断来决定:

   (1)如果形参必须能够改变实参的值,那么就必须使用call by reference。

   (2)否则,实参的值不能被形参改变。如果参数类型是简单类型,使用按值调用。否则,参数类型是类类型的,一般按call by constant reference来传递。

在avg 的声明中,errorFlag参数是通过call by reference来传递的,所以errorFlag的新值返回到实参中。arr和n就不会被avg改变。arr按call by constant reference,因为它的是类类型的,对其进行复制耗费巨大。n通过值来传递,因为它是基本类型,对其进行复制消耗很小。

  参数传递总结如下:

  1. 按值调用适用于不被函数更改的小对象。
  2. call by constant reference适用于不被函数更改的大对象。
  3. call by reference适用于所有可以被函数更改的对象。
举几个例子,对于swap函数,如果我们写成下面这样
#include <iostream>
using namespace std;

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

int main(int argc, char const *argv[])
{
    int i = 3,
        j = 4;
    swap(i, j);
    cout << i << " " << j << endl;
    return 0;
}

我们会发现根本没有实现交换。因为这就是我们上面说的按值调用。
我们改成引址调用试一下
#include <iostream>
using namespace std;

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

int main(int argc, char const *argv[])
{
    int i = 3,
        j = 4;
    swap(i, j);
    cout << i << endl << j << endl;
    return 0;
}

现在就可以正常交换了。


对于C语言,还可以用指针来实现交换。
void swap(int * first, int * second)
{
    int temp = *first;
    *first = * second;
    *second = temp;
}

调用要写成
swap(&x, &y);


最后再看一个按常量引用调用的例子
#include <iostream>
using namespace std;

class A
{
private:
    int value;
public:
    A(int n)
    {
        value = n;
    }
    A(A other)
    {
        value = other.value;
    }
    void Print()
    {
        cout << value << endl;
    }
};

int main(int argc, char *argv[])
{
    A a = 10;
    A b = a;
    b.Print();
    return 0;
}

运行这段代码你会发现无法编译,不过编译器很贴心的提示你是不是想要const A &other,修改后就可以正常运行了。
这里面复制构造函数A(A other) 试图传递A的一个实例,这会在复制构造函数内再调用复制构造函数, 就会一直递归调用从而导致栈溢出。C++的标准不允许复制构造函数传值参数,这时候就要选择按常量引用调用。

数组作为形参:
void display(int the_array[], int num_values)
{
    for(int i = 0; i < num_values; i++)
        cout << the_array[i] << " ";
    cout << endl;
}

在一个形参名字的后面放置一对中括号[]表明这个形参是一个数组,将一个数组传递给一个函数是通过传递这个数组的基地址来实现的;也就是说,总是通过传递引用来传递数组的,这意味着修改形参数组也将修改相应的实参数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值