包括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通过值来传递,因为它是基本类型,对其进行复制消耗很小。
参数传递总结如下:
- 按值调用适用于不被函数更改的小对象。
- call by constant reference适用于不被函数更改的大对象。
- call by reference适用于所有可以被函数更改的对象。
#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;
}
现在就可以正常交换了。
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,修改后就可以正常运行了。
void display(int the_array[], int num_values)
{
for(int i = 0; i < num_values; i++)
cout << the_array[i] << " ";
cout << endl;
}
在一个形参名字的后面放置一对中括号[]表明这个形参是一个数组,将一个数组传递给一个函数是通过传递这个数组的基地址来实现的;也就是说,总是通过传递引用来传递数组的,这意味着修改形参数组也将修改相应的实参数组。