7.2 参数传递
形参的初始化与变量的初始化一样:如果形参具有非引用类型,则复制实参的值;如果形参为引用类型,则它只是实参的别名。
7.2.1 非引用形参
普通的非引用类型的参数通过复制对应的实参实现初始化。当用实参副本初始化形参时,函数并没有访问调用所传递的实参本身,因此不会修改实参的值。
非引用形参表是对应实参的局部副本。对这类形参的修改仅仅改变了局部副本的值。一旦函数执行结束,这些局部变量的值也就没有了。
1. 指针形参
函数的形参可以是指针,此时复制实参指针。与其他非引用类型的形参一样,该类形参的任何改变也仅作用域局部副本。如果函数将新指针值赋给形参,主调函数使用的实参指针的值没有改变。
事实上被复制的指针只影响对指针的赋值。如果函数形参是非const类型的指针,则函数可通过指针实现赋值,修改指针所指向对象的值。
void gcd(int *i)
{
*i = 100; //change the value of the object to which i points...
i = 0; //only change the local pointer i...
}
指针形参是指向const类型还是非const类型,将影响函数调用所使用的实参。我们既可以用int*也可以用const int*类型的实参调用参数为const int*类型的函数;但仅能将int*的实参传递给参数为int*类型的函数。这个差别来源于指针的初始化规则。可以将指向const对象的指针初始化为非const对象,但不可以让指向非const对象的指针指向const对象。
(这是因为形参定义为指向const类型的指针,则规定了形参指向的对象不能在函数体内被修改,即使传进来的是普通的指针;但是如果形参为普通的指针,则函数允许在函数体内对形参指向的对象进行修改,则传入指向const类型的指针会有指针指向的对象被修改的误操作危险,因此不可以传指向const类型的指针)
2. const形参
在调用函数时,如果该函数使用非引用的非const形参,则既可以给该函数传递const实参,也可以传递非const的实参。因为初始化复制了初始化式的值,所以可用const对象初始化非const对象。
(这是因为非引用形参,实参传递进函数后会复制实参的值,因此任何操作都不会改变原实参的值,因此可以传递const实参)
如果将形参定义为非引用的const类型,则在函数中,不可以改变实参的局部副本。由于实参仍然是以副本的形式传递,因此传递给形参为const类型的函数的实参既可以是const对象也可以是非const对象。
3. 复制实参的局限性
复制实参并不是在所有的情况下都适合,不适合复制实参的情况包括:
- 当需要在函数中修改实参的值时。
- 当需要以大型对象作为实参传递时。对实际的应用而言,复制对象所付出的时间和存储空间代价往往过大。
- 当没有办法实现对象的复制时。