每次调用函数时,都会重新创建函数的所有形参,此时传递的实参将初始化形参。形参的初始化与变量的初始化一样:如果形参具有非引用类型,则复制实参值;如果形参为引用类型,则它只是实参的另一个名字。
***非引用形参***
普通的非引用形参通过复制对应实参的值实现初始化。当实参副本初始化形参时,函数并没有访问调用所传递的实参本身,因此不会影响到实参的值。
1、指针形参
void rest(int *ip)
{ *ip = 0;//更改了指向值
ip =0;// 不会更改实参本身
}
指针形参调用过程中不会修改指针实参本身,但可以通过指针修改所指向的对象,如果要保障指针所指向的值,则形参需定义为指向const对象的指针。
void user_ptr(const int* p){ ///}```
指针形参是指向const类型还是非const类型,将影响函数调用所使用的实参。我们既可以用int* 也可以用const int* 类型实参调用user-per函数;但只能用int* 类型的实参传递给rest();
这个差别源之于指针初始化规则:可以将const对象的指针初始化为非const对象,但不可以将非const对象的指针指向const对象。
2、const形参
调用函数时,如果函数使用非引用非const形参,则既可以给函数传递const实参也可以传递非const实参。例如:
const int i =3,j = 6;
int k = rgcd(i,j);
这是因为函数使用的只是实参的副本不涉及 实参本身的修改 故既可以是非const 也可以是const;
如果实参是非引用的const类型:
viod fcn(const int i);
则在函数中不可以改变实参的局部副本,由于实参是以副本传递给形参的故即可以传递const对象也可以是非const对象。 因为无论什么值都不会被修改,就都可以传递了。
复制实参有其局限性,以下几种不适合
1、当需要在函数中修改实参时
2、当传递大型对象时复制实参开销太大
3、没有办法实现对象复制时以上几种情况,有效解决办法是将形参定义为引用或指针类型。